Java 矩阵操作:逻辑无法获取高阶NXN矩阵数据的正确答案

Java 矩阵操作:逻辑无法获取高阶NXN矩阵数据的正确答案,java,algorithm,matrix,collections,Java,Algorithm,Matrix,Collections,我遇到了以下与矩阵操作相关的问题 问题陈述 有一个NxN矩阵,分为N*N个单元。每个单元格都有一个预定义的值。这将作为一个输入。迭代必须发生K次,这也在测试输入中给出。我们必须确保在每次迭代中选择行/列的最佳/min值。最终输出是每次迭代结束时保存的最佳值的累积和 步骤1。对单个行和列求和,并找到行和列的最小和,它可以是行或列,只需要最小的行或列 第二步。将上述金额单独存储 第三步。 最小和行或列的增量元素。一 从1到第k个值重复步骤1、2、3 add the sum at each itera

我遇到了以下与矩阵操作相关的问题

问题陈述

有一个NxN矩阵,分为N*N个单元。每个单元格都有一个预定义的值。这将作为一个输入。迭代必须发生K次,这也在测试输入中给出。我们必须确保在每次迭代中选择行/列的最佳/min值。最终输出是每次迭代结束时保存的最佳值的累积和

步骤1。对单个行和列求和,并找到行和列的最小和,它可以是行或列,只需要最小的行或列

第二步。将上述金额单独存储

第三步。 最小和行或列的增量元素。一

从1到第k个值重复步骤1、2、3

add the sum at each iteration(specified in step2)
输出是在第k次迭代中获得的总和

样本数据

输出数据

二十二

我能够用java编写代码,并对一些示例测试用例进行了测试。结果很好。该代码适用于较低阶的样本数据矩阵,例如2x2,4x4,甚至可以使用迭代次数较少的44x40。然而,当矩阵大小增加到100X100复杂迭代时,我看到预期的输出值与实际输出及其随机值在数字的10s和数百处不同。因为我无法找到输出与输入的正确模式。现在,我真的在调试第500个循环以确定问题,这让我付出了代价。有没有更好的方法或途径来解决与巨大矩阵操作相关的问题。有没有人遇到过类似的问题并解决了

我主要感兴趣的是知道解决给定矩阵问题的正确方法。在java中使用什么样的数据结构。目前,我正在使用原语DS和数组int[]或long[]来解决这个问题。感谢您在这方面的帮助。

哪种数据结构

这里您需要的是一个数据结构,它允许您高效地查询和更新最小和行。最常用的是堆

出于您的目的,最好只实现最简单的类型,即基于数组的二进制堆:

请看这里: 在这里: ..了解实施细节

程序:

将堆的大小初始化为M+N,其中M,N是行数和列数。 在循环之前,预先计算每行和每列的总和,并将它们作为对象添加到堆中。还要添加两个数组A、B,它们分别存储row和columon对象。 现在,根据line sum属性heapify堆数组。这确保堆遵循二进制堆结构parent always>children的标准。阅读源代码,了解更多关于如何为固定阵列轻松实现这一点的信息 对于每个迭代,查看堆数组中的第一个元素。这总是行和最小的一个。如果这是一个行对象,则将sum属性增加N列数,并将B列列表中的每个对象增加1。如果它是一列,请执行相同的操作。 在此之后,始终在下一次迭代之前进行heapify。 最后,只需返回第一个元素的属性

时间复杂性:

每次遍历所有列和行的原始朴素解决方案是

使用堆时,每个步骤的heapify操作都是针对二进制堆的

这意味着总的复杂性要小得多。max项是为了补偿这样一个事实,即在每次迭代中,它可能是递增的行或列

作为旁注,还有其他堆结构类型比二进制堆具有更好的时间复杂度,例如二项式树、斐波那契堆等。然而,这些堆结构要复杂得多,因此具有更高的常数因子开销。因此,对于您的项目,我觉得它们不是必需的,因为它们中的许多都需要惊人的数据集大小来证明恒定因子开销的合理性

此外,它们都支持与二进制堆相同的外部操作,这是由堆的抽象数据结构定义的

heapify是特定于二进制堆结构的内部操作。许多其他的数据结构在理论上是优越的,因为它们隐式地、惰性地执行此操作

哪种数据结构

这里您需要的是一个数据结构,它允许您高效地查询和更新最小和行。最常用的是堆

出于您的目的,最好只实现最简单的类型,即基于数组的二进制堆:

请看这里: 在这里: ..了解实施细节

程序:

将堆的大小初始化为M+N,其中M,N是行数和列数。 在循环之前,预先计算每行和每列的总和,并将它们作为对象添加到堆中。还要添加两个数组A、B,它们分别存储row和columon对象。 N ow heapify相对于line sum属性的堆数组。这确保堆遵循二进制堆结构parent always>children的标准。阅读源代码,了解更多关于如何为固定阵列轻松实现这一点的信息 对于每个迭代,查看堆数组中的第一个元素。这总是行和最小的一个。如果这是一个行对象,则将sum属性增加N列数,并将B列列表中的每个对象增加1。如果它是一列,请执行相同的操作。 在此之后,始终在下一次迭代之前进行heapify。 最后,只需返回第一个元素的属性

时间复杂性:

每次遍历所有列和行的原始朴素解决方案是

使用堆时,每个步骤的heapify操作都是针对二进制堆的

这意味着总的复杂性要小得多。max项是为了补偿这样一个事实,即在每次迭代中,它可能是递增的行或列

作为旁注,还有其他堆结构类型比二进制堆具有更好的时间复杂度,例如二项式树、斐波那契堆等。然而,这些堆结构要复杂得多,因此具有更高的常数因子开销。因此,对于您的项目,我觉得它们不是必需的,因为它们中的许多都需要惊人的数据集大小来证明恒定因子开销的合理性

此外,它们都支持与二进制堆相同的外部操作,这是由堆的抽象数据结构定义的

heapify是特定于二进制堆结构的内部操作。许多其他的解决方案在理论上是优越的,因为它们隐式地、惰性地执行此操作

OKN+N*N解决方案: 您可以只处理列和行的总和,而不直接存储或操作它们。 第一次求和所有列和行,在2*N数组中,第一行是列的和,[0][0]是第一列的和,[0][1]是第二列的和,第二行是行的和,第一行的和,等等。。。 然后执行以下迭代操作:

在数组中查找min。 把它加到答案上。 将N添加到所选行或列的最小值。 如果min为行,则向所有列添加一个,如果为列,则向所有行添加一个。 如果需要任何进一步的解释,请随时发表评论。 OKN+N*N解决方案: 您可以只处理列和行的总和,而不直接存储或操作它们。 第一次求和所有列和行,在2*N数组中,第一行是列的和,[0][0]是第一列的和,[0][1]是第二列的和,第二行是行的和,第一行的和,等等。。。 然后执行以下迭代操作:

在数组中查找min。 把它加到答案上。 将N添加到所选行或列的最小值。 如果min为行,则向所有列添加一个,如果为列,则向所有行添加一个。 如果需要任何进一步的解释,请随时发表评论。
我这样做是为了解决上述问题

        void matrixManipulation() throws IOException {
            int N = Reader.nextInt();
            int[][] matrix = new int[N][N];
            int K = Reader.nextInt();
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    matrix[i][j] = Reader.nextInt();
                }
            }

    //      System.out.println("********Inital position**********");
    //      for (int i = 0; i < N; i++) {
    //          for (int j = 0; j < N; j++) {
    //              System.out.print(matrix[i][j]);
    //          }
    //          System.out.println();
    //      }
    //      System.out.println("********Inital position**********");

            CalculateSum calculateSum = new CalculateSum();

            int[] row = new int[N];
            int[] row_clone = new int[N];

            int[] col = new int[N];
            int[] col_clone = new int[N];

            int test =0;

            for (int kk = 0; kk < K; kk++) {

                row = calculateSum.calculateRowSum(matrix, N);
                row_clone = row.clone();
/* just sort it either Arrarys sort or any other ---starts here*/
    //          for (int i = 1; i < row.length; i++) {
    //              row_orignial[i] = row[i];
    //          }
    //          Arrays.sort(row);
                Node root1 = insert(null, row[0], 0, row.length);
                for (int i = 1; i < row.length; i++) {
                    insert(root1, row[i], 0, row.length);
                }
                sortArrayInOrderTrvsl(root1, row, 0);

    /* just sort it either Arrarys sort or any other ---ends here*/


                col = calculateSum.calculateColumnSum(matrix, N);
                col_clone = col.clone();

/* just sort it either Arrarys sort or any other ---starts here*/
    //          for (int i = 1; i < col.length; i++) {
    //              col_orignial[i] = col[i];
    //          }
    //          Arrays.sort(col);
                Node root2 = insert(null, col[0], 0, col.length);
                for (int i = 1; i < row.length; i++) {
                    insert(root2, col[i], 0, col.length);
                }
                sortArrayInOrderTrvsl(root2, col, 0);

/* just sort it either Arrary.sort or any other---ends here */

                int pick = 0;
                boolean rowflag = false;
                int rowNumber = 0;
                int colNumber = 0;
                if (row[0] < col[0]) {
                    pick = row[0];// value
                    rowflag = true;
                    for (int i = 0; i < N; i++) {
                        if (pick == row_clone[i])
                            rowNumber = i;
                    }
                } else if (row[0] > col[0]) {
                    pick = col[0];// value
                    rowflag = false;
                    for (int i = 0; i < N; i++) {
                        if (pick == col_clone[i])
                            colNumber = i;
                    }
                } else if(row[0] == col[0]){
                    pick = col[0];
                    rowflag = false;
                    for (int i = 0; i < N; i++) {
                        if (pick == col_clone[i])
                            colNumber = i;
                    }
                }
                test= test + pick;

                if (rowflag) {
                    matrix = rowUpdate(matrix, N, rowNumber);
                } else {
                    matrix = columnUpdate(matrix, N, colNumber);

                }
                System.out.println(test);

    //          System.out.println("********Update Count"+kk+" position**********");
    //          for (int i = 0; i < N; i++) {
    //              for (int j = 0; j < N; j++) {
    //                  System.out.print(matrix[i][j]);
    //              }System.out.println();
    //          }
    //          System.out.println("********Update Count"+kk+" position**********");

            }

    //      System.out.println("********Final position**********");
    //      for (int i = 0; i < N; i++) {
    //          for (int j = 0; j < N; j++) {
    //              System.out.print(matrix[i][j]);
    //          }System.out.println();
    //      }
    //      System.out.println("********Final position**********");
    //      System.out.println(test);
        }

我这样做是为了解决上述问题

        void matrixManipulation() throws IOException {
            int N = Reader.nextInt();
            int[][] matrix = new int[N][N];
            int K = Reader.nextInt();
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    matrix[i][j] = Reader.nextInt();
                }
            }

    //      System.out.println("********Inital position**********");
    //      for (int i = 0; i < N; i++) {
    //          for (int j = 0; j < N; j++) {
    //              System.out.print(matrix[i][j]);
    //          }
    //          System.out.println();
    //      }
    //      System.out.println("********Inital position**********");

            CalculateSum calculateSum = new CalculateSum();

            int[] row = new int[N];
            int[] row_clone = new int[N];

            int[] col = new int[N];
            int[] col_clone = new int[N];

            int test =0;

            for (int kk = 0; kk < K; kk++) {

                row = calculateSum.calculateRowSum(matrix, N);
                row_clone = row.clone();
/* just sort it either Arrarys sort or any other ---starts here*/
    //          for (int i = 1; i < row.length; i++) {
    //              row_orignial[i] = row[i];
    //          }
    //          Arrays.sort(row);
                Node root1 = insert(null, row[0], 0, row.length);
                for (int i = 1; i < row.length; i++) {
                    insert(root1, row[i], 0, row.length);
                }
                sortArrayInOrderTrvsl(root1, row, 0);

    /* just sort it either Arrarys sort or any other ---ends here*/


                col = calculateSum.calculateColumnSum(matrix, N);
                col_clone = col.clone();

/* just sort it either Arrarys sort or any other ---starts here*/
    //          for (int i = 1; i < col.length; i++) {
    //              col_orignial[i] = col[i];
    //          }
    //          Arrays.sort(col);
                Node root2 = insert(null, col[0], 0, col.length);
                for (int i = 1; i < row.length; i++) {
                    insert(root2, col[i], 0, col.length);
                }
                sortArrayInOrderTrvsl(root2, col, 0);

/* just sort it either Arrary.sort or any other---ends here */

                int pick = 0;
                boolean rowflag = false;
                int rowNumber = 0;
                int colNumber = 0;
                if (row[0] < col[0]) {
                    pick = row[0];// value
                    rowflag = true;
                    for (int i = 0; i < N; i++) {
                        if (pick == row_clone[i])
                            rowNumber = i;
                    }
                } else if (row[0] > col[0]) {
                    pick = col[0];// value
                    rowflag = false;
                    for (int i = 0; i < N; i++) {
                        if (pick == col_clone[i])
                            colNumber = i;
                    }
                } else if(row[0] == col[0]){
                    pick = col[0];
                    rowflag = false;
                    for (int i = 0; i < N; i++) {
                        if (pick == col_clone[i])
                            colNumber = i;
                    }
                }
                test= test + pick;

                if (rowflag) {
                    matrix = rowUpdate(matrix, N, rowNumber);
                } else {
                    matrix = columnUpdate(matrix, N, colNumber);

                }
                System.out.println(test);

    //          System.out.println("********Update Count"+kk+" position**********");
    //          for (int i = 0; i < N; i++) {
    //              for (int j = 0; j < N; j++) {
    //                  System.out.print(matrix[i][j]);
    //              }System.out.println();
    //          }
    //          System.out.println("********Update Count"+kk+" position**********");

            }

    //      System.out.println("********Final position**********");
    //      for (int i = 0; i < N; i++) {
    //          for (int j = 0; j < N; j++) {
    //              System.out.print(matrix[i][j]);
    //          }System.out.println();
    //      }
    //      System.out.println("********Final position**********");
    //      System.out.println(test);
        }

您是否尝试过使用long[][],可能是因为整数溢出。也可以尝试一下我的答案的算法,这比单纯的方法更容易实现,因此更不容易出现错误,也更高效。我认为您保留了矩阵。pic使用了这个矩阵来表示你不需要保留所有的矩阵,只需要在它的边上保留值,一个2×N的数组,而不是一个N×N的数组。是这样吗?您是否尝试过使用long[][],可能是因为整数溢出。也可以尝试一下我的答案的算法,它比单纯的方法更容易实现,因此更不容易出现错误,也更有效。我认为您保留了矩阵。pic使用了这个矩阵来表示你不需要保留所有的矩阵,只需要在它的边上保留值,一个2×N的数组,而不是一个N×N的数组。是这样吗?这里有两个实现:。两者都是递归的,因此更加直观,尽管效率比迭代的稍低。不幸的是,我不知道为什么您的代码不同于更高的o/p;我能知道的唯一方法是你是否显示了你的代码。很抱歉,我提到的原始java实现缺少heapify操作(又称构建堆)——作者更喜欢一次一个的方法,在我们的例子中,这种方法效率较低。以下是两种实现:。两者都是递归的,因此更加直观,尽管效率比迭代的稍低。不幸的是,我不知道为什么您的代码不同于更高的o/p;我能知道的唯一方法是你是否显示了你的代码。很抱歉,我提到的原始java实现缺少heapify操作,也称为build heap-作者更喜欢一次一个的方法,这在我们的例子中效率较低。@yeppe您是在每次迭代中保留行和列的总和列表,还是只保留整个矩阵,并在上执行操作,将一个元素添加到行或列的所有元素中,然后在每次迭代中再次求和值
ion?@yeppe您是在每次迭代中保留行和列的总和列表,还是只保留整个矩阵,对行或列的所有元素执行操作并实际添加一个元素,然后在每次迭代中再次对值进行总和?您似乎在对二叉树进行排序。。?这在^2最坏的情况下采用log n平均值,而简单的heapify仅适用于此情况。我将实施适用于高阶矩阵的解决方案,并在后天发送,我正在忙于启动活动您似乎正在排序二叉树。。?这在^2最差的情况下采用对数n平均值,而简单的heapify正好采用这种情况。我将实施适用于高阶矩阵的解决方案,并在后天发送,我正在忙于启动活动