递归堆栈溢出错误 java

Stack Overflow Error on recursion java

我需要找到数组中数字之间的最长路径(从大到小)。 我尝试编写 recursive 函数并得到 java.lang.WhosebugError,但由于缺乏知识,我不明白为什么会这样。

首先,我初始化数组并用随机数填充它:

public long[] singleMap = new long[20];
for (int i = 0; i < 20; i++) {
        singleMap[i] = (short) random.nextInt(30);
    }

然后,我尝试找到最长的倒数路线(例如{ 1, 4, 6, 20, 19, 16, 10, 6, 4, 7 , 6, 1 ...} ) 并 return 计算这些数字。

 public int find(long[] route, int start) {
    if (route[start] > route[start + 1]) {
        find(route, start++);
    } else {
        return start;
    }
    return start;
}

这是日志:

 08-23 13:06:40.399 4627-4627/itea.com.testnotification I/dalvikvm:   threadid=1: stack overflow on call to    Litea/com/testnotification/MainActivity;.find:ILI
 08-23 13:06:40.399 4627-4627/itea.com.testnotification I/dalvikvm:   method requires 36+20+12=68 bytes, fp is 0x4189e318 (24 left)
 08-23 13:06:40.399 4627-4627/itea.com.testnotification I/dalvikvm:   expanding stack end (0x4189e300 to 0x4189e000)
 08-23 13:06:40.400 4627-4627/itea.com.testnotification I/dalvikvm: Shrank stack (to 0x4189e300, curFrame is 0x418a3e88)
 08-23 13:06:40.400 4627-4627/itea.com.testnotification D/AndroidRuntime: Shutting down VM
 08-23 13:06:40.400 4627-4627/itea.com.testnotification W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x41a8ed40)
 08-23 13:06:40.414 4627-4627/itea.com.testnotification E/AndroidRuntime: FATAL EXCEPTION: main
                                                                         Process: itea.com.testnotification, PID: 4627
                                                                     java.lang.WhosebugError
                                                                         at itea.com.testnotification.MainActivity.find(MainActivity.java:46)
                                                                         at itea.com.testnotification.MainActivity.find(MainActivity.java:46)

感谢任何解释,因为所有相关问题都没有帮助我。如果我的功能有问题,请指正或解释。

编辑

我忘了说,我用 for 检查每个 "point"

的最长路径
  for (int i = 0; i < singleMap.length - 1; i++) {
        int x = find(singleMap, i);
        System.out.println("steps = " + x);
    }

首先改变

find(route, start++)

find(route, start+1)

因为post-递增returns变量的原始值,所以递归永远不会前进,导致WhosebugError.

您还应该添加一个停止条件,否则您的下一个异常将是 ArrayIndexOutOfBoundsException

正如 Kevin 评论的那样,您还应该使用 find(route, start++); 编辑的值 return 做一些事情。否则调用它根本没有意义。

除了这些问题,你的逻辑也不对。该方法将 return 从数组开头开始的降序序列的最后一个索引,这不会告诉您最长的降序序列。例如,对于 { 1, 4, 6, 20, 19, 16, 10, 6, 4, 7, 6, 1 ...},您的方法将 return 0(数组的第一个索引),因为 route[0] > route[1] 为假。

您需要维护当前最大查找到现在,以及当前值。 所以改变它如下:

public int find(int[] route, int start, int max, int currentMax) {
    if (currentMax > max) {
        max = currentMax;
    }
    if (start == route.length - 1) {
        return max;
    }
    if (route[start] > route[start + 1]) {
        return find(route, start + 1, max, currentMax + 1);
    }
    return find(route, start + 1, max, 1);
}

并以

开头
find(route, 0, 1, 0);

第二种选择是不用递归重写它:

public int find(int[] route) {
    int max = 1;
    int currentMax = 1;
    for (int i = 0; i < route.length - 1; i++) {
        if (route[i] > route[i + 1]) {
            currentMax++;    // If next element is lower increment currentMax
            if (currentMax > max) {
                max = currentMax;   // If currentMax is the new max update max
            }

        } else {
            currentMax = 1;   // If next element is not lower restart from 1
        }
    }
    return max;
}

并将其命名为

find(route);

当您调用 start++ 时,您会执行 后增量。这意味着操作发生 将参数传递给方法后 - 这意味着您的方法只是在第一个参数上不断循环,直到内存用完。 用 start+1 替换它,你会得到一大堆新的异常来玩得开心 ;)

其他用户在这里指出的算法中存在几个问题。但主要问题是这个算法一定不能递归。递归地,你只能找到从零索引开始的递减序列的长度。

正确的算法必须运行遍历整个数组:

public static int find(long[] route) {
    int maxIdx = 0;
    int maxCount = 1;
    for (int i = 1, c = 0; i < route.length; i++) {
        if (route[i] < route[i - 1]) {
            if (++c >= maxCount) {
                maxCount = c;
                maxIdx = i - c;
            }
        } else {
            c = 0;
        }
    }
    return route.length == 0 ? -1 : maxIdx;
}