使用递归时StackOverflow错误

时间:2016-02-08 16:16:49

标签: java recursion stack-overflow

我正在尝试将数字(n)设置为(m)并且对我来说算法有意义但它总是因Stackoverflow错误而崩溃。任何帮助? 这是我的代码:

private static int solve(int n, int m, int steps) {

    if (n > m || n <= 0) {
        //--steps;
        return 0;
    } else if (n == m)
        return steps;

    return Math.min(solve(n * 2, m, steps++), solve(n - 1, m, steps++));
}

更新::: 这段代码非常优雅地解决了这个问题

private static int solve(int n, int m) {

    int steps = 0;
    int cur = n;
    ArrayList<Integer> arr = new ArrayList<>();

   //Setting a list of the best minimum track.
    arr.add(m);
    for (int i = 0; !arr.contains(1); ++i)
        arr.add((int) Math.round((double) arr.get(i) / 2));

   //Aligning the number n to the track and applying it to the best track.(Imagine a stair of steps and you have to reach the top of it, you'll align yourself to one of the steps and then voooom :) )
    while (cur != m) {
        if (arr.contains(cur))
            cur *= 2;
        else
            cur--;

        steps++;
    }
    return steps;
}

1 个答案:

答案 0 :(得分:0)

此算法始终遍历树中的所有可能路径,其中一个分支表示乘法,一个递减1.问题是&#34; 全部&#34 ;,既然有这样的道路:

n = 2 m = 5
branch selection  *2 -1 -1 *2 -1 -1 *2 ...
n after branch     4  3  2  4  3  2  4 ...

永远不会中止。

我怀疑这个算法会对你有所帮助,除了StackOverflowException的明显问题之外,它将在所有情况下解决你的问题。只是一个猜测,但问题是要找到将n转换为m所需的最小乘法和减量数。该算法几乎可以在所有情况下返回0。

正确的解决方案需要BFS,而不像您的解决方案使用的(不正确的)DFS实现。实现正确的DFS遍历所需的访问节点还有Set,必须明确标记无效的解决方案。另一方面,BFS还需要存储访问该值的深度:

public int solve(int n , int m , int step , Map<Integer , Integer> visitedAt){
    //no valid solution  
    if(n > m * 2 || n <= 0)
        return -1;

    //a solution was found at step
    if(n == m)
        return step;

    //the node was already visited with less steps
    if(visitedAt.containsKey(n) && visitedAt.get(n) <= step)
        return -1;

    //store the visited value and the step at which it was visited
    visitedAt.put(n , step);
    //calculate the number of steps required to reach m if the next step is
    //either decrement or multiply by two
    int dec = solve(n - 1 , m , step + 1 , visitedAt);
    int mul = solve(n * 2 , m , step + 1 , visitedAt);

    if(dec == -1)//no possibility to reach m by decrementing n
        return mul;
    else if(mul == -1)//cant reach m by multiplying n by 2
        return dec;
    else //both lead to valid solutions, find minimum number of steps
        return Math.min(dec , mul);
}

虽然这个解决方案并不是BFS算法的优雅实现。但它满足了递归的要求。