我正在尝试实施简单的杆切割问题解决方案。以下是幼稚和动态编程解决方案的代码,
public static int rodCutNaive(int[] a, int n) {
if (n == 1) {
return a[0];
}
int q = 0;
for (int i = 1; i <= n; i++) {
int optimalCut = a[i - 1] + rodCutNaive(a, n - i);
if (q < optimalCut) {
q = optimalCut;
}
}
return q;
}
public static int rodCutDPBottomUp(int[] a, int n) {
if (n == 1) {
return a[0];
}
int[] s = new int[a.length];
s[0] = a[0];
for (int i = 2; i <= n; i++) {
s[i - 1] = a[i - 1];
for (int j = 1; j <= i - 1; j++) {
int optimalCut = a[j - 1] + s[i - j - 1];
if (s[i - 1] < optimalCut) {
s[i - 1] = optimalCut;
}
}
}
return s[n - 1];
}
我用以下方法测试,
public void testRodCutEfficiency() {
int[] a = { 1, 5, 8, 9, 10, 17, 17, 20, 22, 25, 26, 29, 34, 35, 39, 45,
46, 47, 50, 51 };
long t1 = System.nanoTime();
for (int i = 0; i < 1000; i++)
Rod.rodCutNaive(a, a.length);
long t2 = System.nanoTime();
for (int i = 0; i < 1000; i++)
Rod.rodCutDPBottomUp(a, a.length);
long t3 = System.nanoTime();
System.out.println("Problem size = " + a.length);
System.out.println("Naive = " + (t2 - t1));
System.out.println("DP = " + (t3 - t2));
}
输出:
Problem size = 20
Naive = 7989627046
DP = 7913165707
可能是编译器使用朴素版本进行某种尾递归优化,或者JVM是否可能记住先前调用方法的解决方案?
哦,对不起伙计们。这是一个复制粘贴错误。我两次都叫同样的方法。现在我已经改变它了,新的输出是,
Problem size = 20
Naive = 7764056945
DP = 1324966
我试图删除这个问题,但它已经有了答案。
答案 0 :(得分:2)
可能是编译器使用朴素版本进行某种尾递归优化,或者JVM是否可能记住先前调用方法的解决方案?
javac
编译器几乎没有进行任何优化,但是JIT在迭代10,000次后可以对代码进行优化,从而可以对代码进行优化。
HotSpot JVM不支持尾递归优化,也不记得以前的结果。
如果我反复进行测试,我会看到
的小改进Problem size = 20
Naive = 5792466746
DP = 8779592
到
Problem size = 20
Naive = 5701799026
DP = 472377
答案 1 :(得分:1)
你两次都在呼唤rodCutNaive。
答案 2 :(得分:1)
所以是的,基本上,如果你改变第二个基准测试循环以对动态方法进行基准测试,你会得到这个极大的加速:
问题规模= 20
天真= 3838585219
DP = 798526