Java中的优化置换代码

时间:2013-04-24 07:21:34

标签: java memory-management permutation executable-jar performance

这是我从互联网上获得的代码。

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Test<T> {
    public static void main(String args[]) {
        Test<Integer> obj = new Test<Integer>();
        Collection<Integer> input = new ArrayList<Integer>();
        for (int i = 0; i < 14; i++) {
                       input.add(i);

        }

        Collection<List<Integer>> output = obj.permute(input);
        int k = 0;
        Set<List<Integer>> pnr = null;
        for (int i = 0; i <= input.size(); i++)
        {
            pnr = new HashSet<List<Integer>>();
            for(List<Integer> integers : output){
            pnr.add(integers.subList(i, integers.size()));
            }
            k = input.size()- i;
            System.out.println("P("+input.size()+","+k+") :"+ 
            "Count ("+pnr.size()+") :- "+pnr);
        }
    }
    public Collection<List<T>> permute(Collection<T> input) {
        Collection<List<T>> output = new ArrayList<List<T>>();
        if (input.isEmpty()) {
            output.add(new ArrayList<T>());
            return output;
        }
        List<T> list = new ArrayList<T>(input);
        T head = list.get(0);
        List<T> rest = list.subList(1, list.size());
        for (List<T> permutations : permute(rest)) {
            List<List<T>> subLists = new ArrayList<List<T>>();
            for (int i = 0; i <= permutations.size(); i++) {
                List<T> subList = new ArrayList<T>();
                subList.addAll(permutations);
                subList.add(i, head);
                subLists.add(subList);
            }
            output.addAll(subLists);
        }
        return output;
    }
}

import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; public class Test<T> { public static void main(String args[]) { Test<Integer> obj = new Test<Integer>(); Collection<Integer> input = new ArrayList<Integer>(); for (int i = 0; i < 14; i++) { input.add(i); } Collection<List<Integer>> output = obj.permute(input); int k = 0; Set<List<Integer>> pnr = null; for (int i = 0; i <= input.size(); i++) { pnr = new HashSet<List<Integer>>(); for(List<Integer> integers : output){ pnr.add(integers.subList(i, integers.size())); } k = input.size()- i; System.out.println("P("+input.size()+","+k+") :"+ "Count ("+pnr.size()+") :- "+pnr); } } public Collection<List<T>> permute(Collection<T> input) { Collection<List<T>> output = new ArrayList<List<T>>(); if (input.isEmpty()) { output.add(new ArrayList<T>()); return output; } List<T> list = new ArrayList<T>(input); T head = list.get(0); List<T> rest = list.subList(1, list.size()); for (List<T> permutations : permute(rest)) { List<List<T>> subLists = new ArrayList<List<T>>(); for (int i = 0; i <= permutations.size(); i++) { List<T> subList = new ArrayList<T>(); subList.addAll(permutations); subList.add(i, head); subLists.add(subList); } output.addAll(subLists); } return output; } }

当我尝试执行它时,计数7的元素需要很长时间。但是当我尝试14时,我得到了以下异常。

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.toArray(ArrayList.java:329)
    at java.util.ArrayList.addAll(ArrayList.java:530)
    at Test.permute(Test.java:45)
    at Test.permute(Test.java:41)
    at Test.permute(Test.java:41)
    at Test.permute(Test.java:41)
    at Test.main(Test.java:18)
Java Result: 1

我的系统配置是第3代i5,8GB内存。程序运行时,CPU消耗为98-100%。

所以我的问题是:

  • 是否有任何罐子可以有效地进行排列?
  • 我可以在此代码中做些什么来改善性能?

我的要求:

  • 需要置换一组(即超过30个)整数值。

Downvoters请评论原因

4 个答案:

答案 0 :(得分:3)

我建议您在生成每个排列时处理每个排列,而不是首先生成所有排列(因为这需要指数级增长的内存)。这意味着您一次只需要存储一个组合。

您可以生成大小为1的所有排列(如果允许,则生成零)并长大到所有大小的所有排列。

注意:对于您的输出,您只需要计算要生成的数字,而不必实际生成它们。

答案 1 :(得分:1)

您可以稍微增加堆大小:Eclipsecommand line

但是,如果你想要30个元素的所有排列,你需要30! * 30 * 4个字节的内存,即3e + 22 TB ......

答案 2 :(得分:0)

我想也许这里错过了一点。您不断询问是否有更“有效”或“优化”的方式来查找一组数字的所有排列。

30个整数的可能排列数是一个大约32位的数字。一千兆字节的RAM是10位数的字节数。如果你正在谈论将这个问题的所有答案一次性存储在内存中,可以想象,即使你真的拥有整个世界的所有RAM,你也无法做到这一点。

彼得的回答认识到这一点,虽然不可能存储> 30个数字的整个解决方案,但是(更不用说计算时间),可以计算答案的一部分并根据需要生成更多

答案 3 :(得分:0)

这将适用于您正在做的事情。但是,我无法看到减少处理方法的方法。所以这和你能得到的效率一样高。

public static ArrayList<Integer> calPermutations (ArrayList<ArrayList<Integer>> n) {
    if (n.size() <= 0 || n == null) {
        return null;
    }
    ArrayList<Integer> Result = new ArrayList<Integer>();
    for (int i = 0; i < n.size(); i++) {
        Integer num = n.get(i).get(0);
        for (int x = 1; x < n.get(i).size(); x++) {
            num *= n.get(i).get(x);
        }
        Result.add(num);
    }
    return Result;
}

但是,如果Eclipse堆空间错误在Eclipse中继续,您可以转到:

运行 - >运行配置 - &gt;参数

转到VM参数并尝试:

-Xmx2048M

如果这对于你的RAM太大,只需减少数字,直到你找到适合的东西。更多信息here