我认为维基百科上的Java矩阵链乘法算法是不正确的
我几乎可以肯定维基百科页面上的我认为维基百科上的Java矩阵链乘法算法是不正确的,java,algorithm,wikipedia,matrix-multiplication,Java,Algorithm,Wikipedia,Matrix Multiplication,我几乎可以肯定维基百科页面上的matrixChainOrder的Java实现是不正确的。我会改变它,但我不是一个合格的数学记忆学家,我不愿意在没有首先审查我的观察结果的情况下做出改变。我想我要问的是——我的断言正确吗k应改为k+1,因为此版本是用零基索引编写的,不同于在同一页面上首次引入的伪代码版本 protected int[][]m; protected int[][]s; public void matrixChainOrder(int[] p) { int n = p.lengt
matrixChainOrder
的Java实现是不正确的。我会改变它,但我不是一个合格的数学记忆学家,我不愿意在没有首先审查我的观察结果的情况下做出改变。我想我要问的是——我的断言正确吗k应改为k+1,因为此版本是用零基索引编写的,不同于在同一页面上首次引入的伪代码版本
protected int[][]m;
protected int[][]s;
public void matrixChainOrder(int[] p) {
int n = p.length - 1;
m = new int[n][n];
s = new int[n][n];
for (int ii = 1; ii < n; ii++) {
for (int i = 0; i < n - ii; i++) {
int j = i + ii;
m[i][j] = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
int q = m[i][k] + m[k+1][j] + p[i]*p[k+1]*p[j+1];
if (q < m[i][j]) {
m[i][j] = q;
s[i][j] = k + 1; // <-- this is the necessary change
}
}
}
}
}
通过不将1添加到k(因为索引移位为零),可以获得错误的矩阵链接位置。首先,不能在0处插入矩阵。s的正确输出应为:
s:
0 1 1 1
0 0 2 3
0 0 0 3
0 0 0 0
s[0][3]=1表示在A(BCD)处拆分ABCDs[1][3]=3表示在A((BC)D)处拆分A(BCD)
就是这样-一个最佳成本计算。不,实现是正确的。改变
s[i][j]=k代码>至s[i][j]=k+1代码>将破坏程序
您可以通过将代码复制到一个名为MatrixOrderOptimization.java的文件中,并添加一个类似以下的main
函数来测试这一点:
public static void main(String[] args) {
MatrixOrderOptimization moo = new MatrixOrderOptimization();
moo.matrixChainOrder(new int[]{ 3, 2, 4, 3, 2 });
moo.printOptimalParenthesizations();
}
尝试编译和运行程序,无论是否有您建议的更改。您将看到,进行建议的更改会导致无效的索引值
为什么会这样?那么,解的值s[i][j]
被定义为“达到最佳成本的指数”。这就是它在伪代码中的名称,也是Java实现处理它的方式
您指出,在伪代码中,索引从1开始,而在Java实现中,索引从0开始。然而,s[i][j]
在这两种情况下的含义都是达到最佳成本的指标
如果您通过添加一个索引来修改索引,那么您就放弃了程序的其余部分。这样想:不要改变s[i][j]=k代码>至s[i][j]=k+1
,在printOptimizations
中更改数组访问。在代码引用s[i][j]
的每一行中,将其更改为s[i][j]+1
换言之,替换
printOptimalParenthesizations(s, i, s[i][j], inAResult);
printOptimalParenthesizations(s, s[i][j] + 1, j, inAResult);
与
这些更改的效果与您建议的更改完全相同。在这里,当我们将其从数组中取出时,我们将向最优索引添加一个,而当您将其粘贴到数组中时,您建议向最优索引添加一个
在这两种情况下,值都不正确,程序崩溃。这是因为s[i][j]
的含义不是最佳索引加1。这只是最佳指标
Java程序希望s
包含最佳索引,因为它理解最佳索引,这意味着它们从零开始。如果通过添加一个值来更改这些值,则违反了索引的含义并破坏了程序。s[i][j]=k
其中k
“=达到最佳成本的索引”。如果将1添加到k
,它将不再是索引。@DTing k表示一个断点,其中矩阵用括号分隔,以确定操作顺序。如果在第一个算法中k=2,则矩阵ABCD将在(AB)CD处拆分,但在我建议的版本中,如果不使用k+1,则会在(ABC)D处拆分,因为它是基于零的索引。@DTing我花了很多时间研究它,你是对的。我专注于基于1的语言和基于0的语言,比较它们的结果,好像它们应该是相等的。只有成本表是相等的。索引表是特定于实现或语言的。
printOptimalParenthesizations(s, i, s[i][j], inAResult);
printOptimalParenthesizations(s, s[i][j] + 1, j, inAResult);
printOptimalParenthesizations(s, i, s[i][j]+1, inAResult);
printOptimalParenthesizations(s, s[i][j]+1 + 1, j, inAResult);