递归需要很长时间,Android

时间:2013-12-26 17:34:14

标签: android performance recursion

我的算法需要一些帮助。我试图寻找类似的问题,但找不到令我满意的东西。

我的代码在我的桌面上执行速度非常快(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代码会增加项目的复杂性,我不愿意(还)走这条路。

1 个答案:

答案 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;
}