递归堆栈溢出错误 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;
}
我需要找到数组中数字之间的最长路径(从大到小)。
我尝试编写 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;
}