Рекурсивная память Java

Решаю проблему в codeforces. Программирую на Java.

В этой задаче я создаю массив dp[N][5][3] целых чисел (примерно N*5*3 рекурсивных вызовов). Когда N равно миллиону, моя программа падает в памяти, однако лимит памяти составляет около 256 MB. То же решение на C++ идет хорошо, при этом съедает в два раза меньше памяти. Почему это так?

Вот код:

    private int MAX = (int) 1E6 + 6;
    private int[] cnt;
    private int[][][] dp;

    private int min(int a, int b) {
        return a > b ? b : a;
    }

    private int max(int a, int b) {
        return a < b ? b : a;
    }

    private int solve(int x, int t1, int t2) {
        // element x,   x used t1 times,   x + 1 used t2 times
        if (dp[x][t1][t2] != -1)
            return dp[x][t1][t2];
        else if (x + 3 > MAX)
            return dp[x][t1][t2] = (cnt[x] - t1) / 3 + (cnt[x + 1] - t2) / 3;

        int ans0, ans1 = 0, ans2 = 0;
        ans0 = (cnt[x] - t1) / 3 + solve(x + 1, t2, 0);
        int min = min(cnt[x] - t1, min(cnt[x + 1] - t2, cnt[x + 2]));
        if (min >= 1)
            ans1 = (cnt[x] - t1 - 1) / 3 + 1 + solve(x + 1, t2 + 1, 1);
        if (min >= 2)
            ans2 = (cnt[x] - t1 - 2) / 3 + 2 + solve(x + 1, t2 + 2, 2);
        return dp[x][t1][t2] = max(ans0, max(ans1, ans2));
    }

    private void solve(InputReader in, PrintWriter out) {
        int n = in.nextInt();
        int m = in.nextInt();

        cnt = new int[MAX];
        for (int i = 0; i < n; i++) cnt[in.nextInt()]++;

        dp = new int[MAX][5][3];
        for (int i = 0; i <= m; i++)
            for (int j = 0; j < 5; j++)
                for (int k = 0; k < 3; k++)
                    dp[i][j][k] = -1;

        out.println(solve(1, 0, 0));
    }

Нет необходимости понимать логику функции решения. Здесь рекурсивный метод просто вызывается примерно N*5*3 раз.

Можете ли вы показать, как вы создаете эти массивы?

Arthur Attout 11.03.2019 14:58

Вы можете определить, сколько памяти разрешено использовать Java. Поищи в Гугле.

Idos 11.03.2019 15:01

Измените размер кучи, чтобы позволить Java потреблять больше памяти. Это можно сделать через ide, который вы используете.

Simeon Ikudabo 11.03.2019 15:18

@ArthurAttout вот ссылка codeforces.com/contest/1110/submission/51139125

Lev Polyakov 12.03.2019 14:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
4
141
2

Ответы 2

Если вам абсолютно необходим такой большой массив (и я рекомендую вам дважды подумать, прежде чем использовать этот большой массив и искать лучшее решение для памяти), вы можете увеличить максимальный размер памяти java-программы во время запуска, используя аргумент -Xmx

Например: java -jar myProgram.jar -Xmx1G использовать 1 ГБ в качестве памяти максимального размера кучи (обратите внимание, что если этого недостаточно, вы можете увеличить больше)

Обратите внимание, что вы также можете указать начальный размер кучи с помощью аргумента -Xms

Это отличная идея, но этот код работает на их серверах. Использует ли java больше памяти для своих типов данных?

Lev Polyakov 12.03.2019 14:11

Это зависит от вашего кода. Прежде всего, если вы работаете с рекурсивным методом, jvm хранит каждый объект в куче и содержит ссылку на каждый объект в стеке. Если вы хотите предотвратить эту ошибку, вы должны инициализировать неиспользуемый объект нулем.

Вот код codeforces.com/contest/1110/submission/51139125

Lev Polyakov 12.03.2019 14:12

Другие вопросы по теме