Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我认为维基百科上的Java矩阵链乘法算法是不正确的_Java_Algorithm_Wikipedia_Matrix Multiplication - Fatal编程技术网

我认为维基百科上的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)处拆分ABCD
s[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);