【问题标题】:Filling a jagged 2d array first by columns首先按列填充锯齿状二维数组
【发布时间】:2025-11-23 00:20:02
【问题描述】:

我想编写一个函数,它接受一个二维数组并用1...n 填充它,但首先计算列而不是行:

input = {{0, 0, 0, 0}, {0}, {0}, {0, 0}};

the output should be: {{1, 5, 7, 8}, {2}, {3}, {4, 6}};

如果我要遍历行然后得到列:

private static void fill1(int[][] input) {
    int count = 1;
    for (int i = 0; i < input.length; i++) {
        for (int j = 0; j < input[i].length; j++) {
            input[i][j] = count;
            count++;
        }
    }
}

如何先循环遍历列?

【问题讨论】:

    标签: java arrays multidimensional-array jagged-arrays


    【解决方案1】:

    要首先按列填充二维数组,您可以使用两个嵌套的。对于锯齿状二维数组,当您事先不知道每行中的列数时,您可以在列仍然存在时在外部流中进行遍历。

    /**
     * @param arr array that should be populated.
     * @return maximum row length, i.e. columns count.
     */
    private static long populate(int[][] arr) {
        AtomicInteger counter = new AtomicInteger(1);
        return IntStream
                // traverse through the array columns
                .iterate(0, i -> i + 1)
                // process the array rows where
                // this column is present
                .mapToLong(i -> Arrays.stream(arr)
                        // filter those rows where
                        // this column is present
                        .filter(row -> row.length > i)
                        // assign a value to the element and increase the counter
                        .peek(row -> row[i] = counter.getAndIncrement())
                        // count of rows where this column is present
                        .count())
                // while the columns are still present
                .takeWhile(i -> i > 0)
                // max columns count
                .count();
    }
    
    public static void main(String[] args) {
        int[][] arr = {{0, 0, 0, 0, 0, 0}, {0, 0}, {0}, {0, 0, 0}};
    
        System.out.println("Max columns count: " + populate(arr));
        System.out.println(Arrays.deepToString(arr));
    }
    

    输出:

    Max columns count: 6
    [[1, 5, 8, 10, 11, 12], [2, 6], [3], [4, 7, 9]]
    

    另见:How to create a new List from merging 3 ArrayLists in round robin style?

    【讨论】:

      【解决方案2】:

      要首先迭代锯齿状二维数组的列来填充它,您必须事先知道最大列数,但如果您不知道,可以迭代到 Integer.MAX_VALUE 并检查每个如果列仍然存在,请执行步骤:

      int[][] arr = {{0, 0, 0, 0}, {0}, {0}, {0, 0}};
      
      int count = 1;
      for (int col = 0; col < Integer.MAX_VALUE; col++) {
          boolean max = true;
          for (int row = 0; row < arr.length; row++) {
              if (col < arr[row].length) {
                  arr[row][col] = count;
                  count++;
                  max = false;
              }
          }
          if (max) break;
      }
      
      for (int[] row : arr) {
          System.out.println(Arrays.toString(row));
      }
      

      输出:

      [1, 5, 7, 8]
      [2]
      [3]
      [4, 6]
      

      另见:How do you rotate an array 90 degrees without using a storage array?

      【讨论】:

        【解决方案3】:

        如果您处理的是常规二维矩阵,其中所有行的列数相同,则代码将是逐行填充矩阵的代码的简单修改:

        private static void fill1(int[][] input) {
            int count = 1;
            for (int j = 0; j < input[0].length; j++) {
                for (int i = 0; i < input.length; i++) {
                    input[i][j]= count;
                    count++;
                }
            }
        }
        

        对于参差不齐的 2d 数组,该过程基本相同,但增加了一些曲折:

        1. 您需要做一些额外的工作来确定可能有多少列(即最大行长)
        2. 您需要为给定行/列位置没有单元格的情况做好准备。

        对前面代码的以下修改解决了这些问题:

        private static void fill1(int[][] input) {
            int maxCols = input[0].length;
            for (int i = 1; i < input.length; ++i) {
                if (input[i].length > maxCols) {
                   maxCols = input[i].length;
                }
            }
            int count = 1;
            for (int j = 0; j < maxCols; j++) {
                for (int i = 0; i < input.length; i++) {
                    if (j < input[i].length) {
                        input[i][j]= count;
                        count++;
                    }
                }
            }
        }
        

        【讨论】:

          【解决方案4】:

          您可以先转置输入,执行 fill1 代码,然后再次转置输出。
          有关如何在 Java 中转置二维数组,请参阅此问题:java multi-dimensional array transposing

          【讨论】: