Привет, я получил java .lang.OutOfMemoryError: Java пространство кучи при попытке решить эту проблему алгоритма, что можно сделать? - PullRequest
0 голосов
/ 24 марта 2020

Проблема аналогична сумме подмножеств, в которой мы определяем, имеет ли список чисел подмножество, которое дает заданную сумму, но в этом случае нам разрешается создавать подмножество из элементов списка p, только если он равен или больше соответствующего элемента в другом списке q. Кроме того, вместо суммы значений элементов, k является количеством элементов, которые могут быть добавлены. поэтому, если k равно 3, нам нужно выбрать 3 элемента из списка p, но эти элементы не могут быть меньше соответствующего элемента списка q. Я новичок в динамическом c программировании и рюкзаке, пожалуйста, помогите мне.

public static List<Integer> kthPerson(int k, List<Integer> p, List<Integer> q) {

    List<Integer> q1 = new ArrayList<>();
    q1.addAll(q);
    Collections.sort(q1);

    int maxQ = q1.get(q1.size()-1);

    List<Integer> res = new ArrayList<>();

    int[][] dp = new int[k+1][maxQ+1];
    for(int[] d:dp){
        Arrays.fill(d, 0);
    }

    for (int u = 0; u < maxQ; u++) {
        int count = 0;
        for (int i = 0; i < p.size(); i++){
            if (p.get(i) >= u){
                dp[count][u] = i+1;
                count++;
            }
            if (count == k){
                break;
            }
        }
    }

    for (int s = 0; s < q.size(); s++) {
        res.add(dp[k-1][q.get(s)]);
    }
    return res;
}

/*if you want to test*/
public static void main(String args[]) {



        List<Integer> p = new ArrayList<>();

        p.add(1);
        p.add(4);
        p.add(4);
        p.add(3);
        p.add(1);
        p.add(2);
        p.add(6);

        List<Integer> q = new ArrayList<>();

        q.add(1);
        q.add(2);
        q.add(3);
        q.add(4);
        q.add(5);
        q.add(6);
        q.add(7);

        kthPerson(2, p, q);


    }
 /*you will get 
2
3
3
3
0
0
0. which is desired result but when the input is really large I get the java heap error*/


Ответы [ 2 ]

2 голосов
/ 27 марта 2020

Ну, правда, вам не нужно динамическое программирование c для этого вопроса. Ни один случай на самом деле не основан на предыдущих случаях.
Поэтому вы можете написать эту функцию:

public static List<Integer> kthPersonNew(int k, List<Integer> p, List<Integer> q) {
    List<Integer> res = new ArrayList<>();

    for (int limit : q) {
        int count = 0;
        boolean added = false;
//      For each person index
        for (int i = 0; i < p.size(); i++) {
//          If this person is higher than the needed limit - count it
            if (p.get(i) >= limit) {
                count++;
//              If you have counted k persons than add the kth person to res and break
                if (count == k) {
                    res.add(i + 1);
                    added = true;
                    break;
                }
            }
        }
//      In case no one was added than add 0
        if (!added) {
            res.add(0);
        }
    }
    return res;

}

И он выдает тот же вывод для предоставленного вами теста.

p = [1, 4, 4, 3, 1, 2, 6]
q = [1, 2, 3, 4, 5, 6, 7]
=>
res = [2, 3, 3, 3, 0, 0, 0]

Теперь я уверен, что эта программа не вызовет java.lang.OutOfMemoryError, так как вы используете только один массив и он имеет одинаковую длину как q.
Это должно решить вашу проблему.


Редактировать:
Похоже, что новый алгоритм хорош для памяти, но недостаточно быстр, предполагая, что q мы всегда можем это использовать и убедиться, что временная сложность всегда меньше, чем O(q * k + n). Поскольку каждый элемент, который не соответствует текущему пределу, не будет соответствовать будущим пределам.

Нам понадобится вспомогательный класс:

class Element{
    private int index;
    private int value;

    public Element(int index, int value){
        this.index = index;
        this.value = value;
    }

    public int getIndex(){
        return this.index;
    }

    public int getValue(){
        return this.value;
    }

    @Override
    public String toString(){
        return value + " " + index;
    }

    public void print(){
        System.out.println(this);
    }
}

, чтобы мы могли помните старый индекс переменных даже после удаления.

и новую функцию:

public static List<Integer> kthPersonFast(int k, List<Integer> p, List<Integer> q) {
    List<Integer> res = new ArrayList<>();

    List<Element> elements = new LinkedList<Element>();
    for (int i = 0; i < p.size(); i++) {
        elements.add(new Element(i, p.get(i)));
    }

    for (int limit : q) {
        int count = 0;
        boolean added = false;
//          For each person         
        Iterator<Element> itr = elements.iterator(); 
        while (itr.hasNext()) { 
            Element person = itr.next(); 

//              If this person is higher than the needed limit - count it
            if (person.getValue() >= limit) {
                count++;
//                  If you have counted k persons than add the kth person to res and break
                if (count == k) {
                    res.add(person.getIndex() + 1);
                    added = true;
                    break;
                }
            } else {
//                  If the person didn't fit for that limit it will not fit to any other limit
//                  since we are assuming the limits are always growing
                itr.remove();
            }
        }
//          In case no one was added than add 0
        if (!added) {
            res.add(0);
        }
    }
    return res;
}

Вам также нужно будет импортировать:

import java.util.Iterator;
import java.util.LinkedList;

Это должно быть .

Удачи

0 голосов
/ 01 апреля 2020

Вам может понадобиться заглянуть в другие части вашей программы, чтобы узнать, можете ли вы удалить неиспользуемые объекты. В этом случае нам нужно будет увидеть больше кода. При этом вы можете получить следующие преимущества, если вы еще не пробовали:

, если вы используете 64-разрядную JVM, вы можете просто увеличить размер кучи.

java -Xmx4G -jar MyProgram.jar

https://javarevisited.blogspot.com/2011/05/java-heap-space-memory-size-jvm.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...