我的算法需要一些帮助。我试图寻找类似的问题,但找不到令我满意的东西。
我的代码在我的桌面上执行速度非常快(0.3秒)但是当部署在Android设备(不是模拟器,三星S3)上时,执行速度非常慢,可能需要一分钟。我想知道我有什么可能使它运行得更快,比如1s。
我已经读过Android中的大量递归会导致内存分配/ GC问题,这可能就是这种情况吗?怎么避免呢?去迭代?
代码在这里:
public class CombinationsQuestion {
public static void main(String[] args) {
CombinationsQuestion comb = new CombinationsQuestion();
long start = new Date().getTime();
List<String> combinations = comb.combinations("12345678".toCharArray());
long end= new Date().getTime();
for(String s : combinations) {
System.err.println(s);
}
System.err.println(combinations.size());
System.err.println("took " + (end - start) + " ms");
}
public List<String> combinations(char[] word) {
List<String> list = new ArrayList<String>();
if (word.length == 1) {
list.add(String.valueOf(word));
} else {
char[] sub = new char[word.length - 1];
for (int i = 0; i < word.length; i++) {
System.arraycopy(word, 0, sub, 0, i);
System.arraycopy(word, i + 1, sub, i, sub.length - i);
list.add(String.valueOf(word[i]));
list.addAll(concatenate(word[i], combinations(sub)));
}
sub = null;
}
return list;
}
public List<String> concatenate(char c, final List<String> lst) {
List<String> ret_set = new ArrayList<String>(lst.size());
for (String s : lst) {
ret_set.add(c + s);
}
return ret_set;
}
}
我可以通过临时分配像Android: Increase call stack size这样的更大的堆栈来解决它吗?
提前谢谢!
PS。我知道这会产生很多字符串。
- 更新 -
我调试了代码,看起来Dalvik在递归期间正在做重GC。这不会发生在常规桌面上。
所以这样做的唯一方法是尝试重用变量而不是实例化对象太多。当然,在生成Strings时这有点棘手但你可以在某种程度上使用StringBuilder / StringBuffer。
我发现一篇文章说使用NDK可以解决这个问题,但添加NDK代码会增加项目的复杂性,我不愿意(还)走这条路。
答案 0 :(得分:0)
你需要打印整套吗?如果没有,您可以使用标准排列公式,这些公式应该运行得更快。
/**
* The setSize in the question's example would be 8 since there are 8 possible numbers
* to choose from in the set "12345678"
*/
public static void solvePermutation(int setSize){
long p = 0;
for(int subSet=1; subSet<setSize+1; subSet++){
p = p + permutation(setSize,subSet);
}
System.out.println(p);
}
/**
* p(n,r) = n!/((n-r)!)
* http://www.calctool.org/CALC/math/probability/combinations
*
* @param n set size
* @param r subset size
* @return
*/
public static long permutation(long n, long r){
long p = factorial(n)/
(factorial(n-r));
return p;
}
/**
* http://stackoverflow.com/a/7879559/1361695
*
* @param n
* @return
*/
public static long factorial(long n) {
long fact = 1; // this will be the result
for (long i = 1; i <= n; i++) {
fact *= i;
}
return fact;
}