【发布时间】:2021-12-15 15:29:17
【问题描述】:
我认为我关于 Stack Overflow 的第一个问题应该是关于堆栈溢出错误......
我使用递归算法解决了 Code Wars 中的“观察到的 PIN”问题:
https://www.codewars.com/kata/5263c6999e0f40dee200059d
import java.util.List;
import java.util.ArrayList;
public class ObservedPin {
static StringBuilder sb = new StringBuilder();
static int[] digits;
static int[] index;
static List<String> perms = new ArrayList<String>();
static int[][] nums = {{0, 8}, {1, 2, 4}, {1, 2, 3, 5}, {2, 3, 6},
{1, 4, 5, 7}, {2, 4, 5, 6, 8}, {3, 5, 6, 9}, {4, 7, 8},
{5, 7, 8, 9, 0}, {6, 8, 9}};
public static List<String> getPINs(String observed) {
digits = new int[observed.length()];
index = new int[observed.length()];
for (int i = 0; i < digits.length; i++) {
digits[i] = observed.charAt(i) - 48;
}
permutations(0);
return perms;
}
public static void permutations(int level) {
if (index[level] == nums[digits[level]].length) {
if (level == 0) {
return;
} else {
index[level] = 0;
index[level - 1]++;
level = 0;
}
} else {
if (level == digits.length - 1) {
//addPinToList(); **** commented out to see if this affected the required memory ****
index[level]++;
} else {
level++;
}
}
permutations(level);
}
public static void addPinToList() {
for (int i = 0; i < digits.length; i++) {
sb.append(Integer.toString(nums[digits[i]][index[i]]));
}
perms.add(sb.toString());
sb.setLength(0);
}
}
在看到其他“最佳实践”和“聪明”的解决方案后,我意识到这绝对不是要走的路,我应该以不同的方式解决问题。无论如何,在测试我的解决方案时,我将一个具有最高可能排列数的 PIN 号传递给了 getPINs 方法。任何完全由 5 和 8 组成的 PIN 将产生 320,625 种可能的排列。我使用了 PIN 58585858。 当我运行代码时,我得到了 StackOverflowError。我对代码进行了一些我认为可能会有所帮助的更改,但没有任何效果。最终我增加了堆栈大小并且代码运行良好。只是出于兴趣,我注释掉了将排列添加到“perms”列表的行,认为这也会减少所需的内存,但是当使用默认的 1Mb 堆栈大小时,我得到了同样的错误。 如果递归方法不创建任何参数或对象,或者对任何现有参数/对象的大小有任何影响,为什么它会占用这么多内存? JVM 是否为每次递归创建一个新的堆栈帧,所以是这些帧占用了内存?
我正在自学,我对此很陌生,您可能已经猜到了。
【问题讨论】: