Java 使用递归时发生堆栈溢出错误

Java 使用递归时发生堆栈溢出错误,java,recursion,stack-overflow,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 M

我试图得到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。问题是全部,因为还有这样一条路径:

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遍历所需的已访问节点,还有一个附加集,必须显式标记无效的解决方案。另一方面,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算法的优雅实现。但是它满足了递归的要求。

那么,您从什么值开始呢?您采取了哪些诊断步骤来检查发生了什么?您是否尝试过通过代码进行调试?提示:调用solve2,3需要调用solve1,3。。。这反过来会调用solve2,3。。。你认为这将如何解决?老实说,不清楚你想计算什么…我将采用200的无限递归,Alex。建议:你的return语句在进行计算的同时递增变量。这太难解释了;将增量步骤与计算步骤分开。@JonSkeet我尝试使用4、6之类的值。您的测试用例是正确的,但并不总是正确的;因为1号有一个特殊情况;我想说的是让我们试试4,6这个不行。试试1,5,0@Navidsry,我刚刚注意到我复制了OP提供的代码中的另一个错误。我会改正的。现在应该可以为您的示例输入工作了。@Navid我还用paul先生建议的算术解更新了帖子。工作正常,时间复杂度非常高。