我有一个函数来计算g(n),其中g(n)= f(n,n)并且可以递归地定义为
f(i,j)= 1 3 (f(i - 1,j)+ f(i - 1,j - 1)+ f(i,j - 1)),
f(0,0)= 0; f(i,0)= 1,i> 0; f(0,j)= 1,j> 0
static final Map<List<Double>, Double> CACHE = new HashMap<>();
private static double f(double i, double j) {
if (i == 0.0 && j == 0.0) return 0.0;
if (i == 0.0 || j == 0.0) return 1.0;
List<Double> key = Arrays.asList(i, j);
Double a = CACHE.get(key);
if (a != null)
return a;
double result = (1.0 / 3) * (f(i - 1, j) + f(i - 1, j - 1) + f(i, j - 1));
CACHE.put(key, result);
return result;
}
private static double g(double n) {
return f(n, n);
}
}
我试图计算n = 10 ^ 1,10 ^ 2,10 ^ 3,10 ^ 4,10 ^ 5,10 ^ 6的值。前3个结果计算得很好,但接下来程序崩溃了:
Exception in thread "main" java.lang.StackOverflowError
at java.util.HashMap$TreeNode.getTreeNode(HashMap.java:1873)
at java.util.HashMap.getNode(HashMap.java:575)
at java.util.HashMap.get(HashMap.java:556)
at javaapplication7.Question3.f(Question3.java:72)
有人能看到解决这个问题的方法吗?那么存储和运行时间的复杂性又是什么呢?
答案 0 :(得分:1)
问题就像异常的名称一样:StackOverflowError
。对于n = 10000的情况,我们需要调用函数f
10000 * 10000次,并且所有函数调用都保存在堆栈内存中,这会导致堆栈溢出。
因此,一个选项是可以增加Java堆栈大小。
或者,您可以考虑从递归方法转变为迭代方法。
观察:要计算状态f(i, j)
,我们只需要知道状态f(i - 1, j), f(i - 1, j - 1)
和状态f(i, j - 1)
,它只需要两个数组,一个保存当前{{1 },一个包含i
的结果。所以我们可以提出这样的迭代解决方案,只需要O(2 * n)空间:
i - 1