用逻辑填充int[2000][2000]时发生java StackOverflow错误
我需要用一些逻辑填充int[2000][2000]
矩阵
填充数组的我的代码:
// n: (1 to 2000)
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
uniMatrix[i][j] = (((calc(i * j * i * j)) & 1) == 0) ? 0 : 1;
}
}
这里:i * j * i * j
是我对i*j
平方的理解。
calc()
是一种用于获取值的方法。然后,我检查calc()
返回的值是偶数还是奇数。如果它是偶数,我将0
存储在(i, j)
上的矩阵中,否则我将1
存储在其中
我的calc()
函数如下所示:
private static int calc(int n){
// value of n=calc(1 | 2 | 3) is known
if(n < 4) return n;
// if value is present in HashMap, return it (don't calculate again)
if(map.containsKey(n)) {
return map.get(n);
}
// calculate the answer
int answer = 1 * calc(n-1) + 2 * calc(n-2) + 3 * calc(n-3);
// store it in HashMap so that we don't have to recalculate it
map.put(n, answer);
return answer;
}
现在,如果n
是13,它将创建一个[13x13]矩阵。但是,对于n=14
,它在map.containsKey(n)
处抛出一个StackOverflowError
。我需要能够制作[2000x2000]矩阵
我知道问题可能是递归。但是,有办法解决这个问题吗?我可以用位集做些什么吗(我不知道怎么做)
我可以使用其他数据类型矩阵:String[][]
或boolean[][]
。我不能使用Java SDK/JDK之外的库
编辑:它不是“What is StackOverflower?”(什么是StackOverflower?)的副本,我知道这是什么,我知道它们为什么会发生。我需要帮助找到一种替代我的方法来防止这个错误
# 1 楼答案
我们只对模2的结果感兴趣,所以所有的计算都可以模2进行。然后递归减少为(为计算模2编写计算):
我们看到,下一个值只取决于固定距离内的两个前一个值,因为每个值的数字范围是有限的(只能是0或1),我们知道序列最终必须是周期的。一些实验表明,周期为7
因此,模2的值为(对于n>;=1):
# 2 楼答案
无法计算所需值范围的
calc
。在i = j = 216
您会得到一个整数溢出(i * j * i * j
的结果变为负数),因此calc
的结果可能不正确。更糟糕的是,你的备忘录map
的大小也会爆炸好消息是你实际上不需要计算它。 看看这个表达:
您不需要计算值,只需要知道值是偶数还是奇数。你可以知道,用简单的数学。
calc
实现的核心是:我们知道前三个值是1,2,3。 事实上,知道它们是奇数、偶数、奇数就足够了。 之后的值可以基于简单的数学计算:
现在,让我们看看由
calc
计算的前两个值,并验证决定该值是奇数还是偶数的逻辑:如果您注意到,出现了重复模式:
只有0会破坏模式,在这种情况下,该值为0。 因此,您的实现可以这样重写,而不会有堆栈溢出的风险:
对于0,由于它不遵循该模式,因此需要进行特殊处理。对于1,x-2为负。由于0和1的正确值是其本身,因此if(x<;2)分支是处理这些情况的简单方法