【问题标题】:Loop diagonally through two dimensional array通过二维数组对角循环
【发布时间】:2013-12-23 13:52:19
【问题描述】:

我编写了以下代码来遍历数组的一半对角线:

String[][] b = [a,b,c]
               [d,e,f]
               [g,h,i];  

public void LoopDiag()
   for (int i = b.length - 1; i > 0; i--) {
       String temp = "";
       for (int j = 0, x = i; x <= b.length - 1; j++, x++) {
          temp = temp+b[x][j];
       }
       System.out.println(temp)
   }


   for (int i = 0; i <= b.length - 1; i++) {
        String temp = "";
        for (int j = 0, y = i; y <= b.length - 1; j++, y++) {
        temp = temp+b[j][y];
        }
        System.out.println(temp);
   }
}

现在它打印对角线,即当前输出:

g dh aei bf c

如何让它打印另一半对角线,即所需的输出:

a db gec hf i 

【问题讨论】:

  • 按照我们看到的格式格式化您的输出
  • 你试过自己解决吗?你面临什么特别的困难?是你的功课吗?

标签: java for-loop multidimensional-array


【解决方案1】:

类型1:我们可以很容易地用python解决这个问题

代码:

r,c=map(int,input().split())
mat=[[str(ch) for ch in input().split()]for _ in range(r)]
for i in range(r*c-2):
    lis=[]
    for j in range(r):
        for k in range(c):
            if k+j==i:
                lis.append(mat[j][k])
    print(*lis[::-1])

输出:

5 5
a b c d e
f g h i j
k l m n o
p q r s t
u v w x y

a
f b
k g c
p l h d
u q m i e
v r n j
w s o
x t
y

【讨论】:

    【解决方案2】:

    初始化数组仅用于测试目的:

        int dim = 5;
        char ch = 'A';
        String[][] array = new String[dim][];
        for( int i = 0 ; i < dim ; i++ ) {
            array[i] = new String[dim];
            for( int j = 0 ; j < dim ; j++, ch++ ) {
                array[i][j] = "" + ch;
            }
        }
    

    输出我们的矩阵:

        for( int i = 0 ; i < dim ; i++ ) {
            for( int j = 0 ; j < dim ; j++, ch++ ) {
                System.out.print( array[i][j] + " " );
            }
            System.out.println();
        }
        System.out.println( "============================" );
    

    解决方案

    对角线的元素索引有一个规则 - 它们的总和在一条对角线上是恒定的:

    变体 1

    使用两个循环提取所有对角线。

    第一个循环提取对角线的上半部分:

        for( int k = 0 ; k < dim ; k++ ) {
            for( int j = 0 ; j <= k ; j++ ) {
                int i = k - j;
                System.out.print( array[i][j] + " " );
            }
            System.out.println();
        }
    

    第二个循环迭代对角线的下半部分:

        for( int k = dim - 2 ; k >= 0 ; k-- ) {
            for( int j = 0 ; j <= k ; j++ ) {
                int i = k - j;
                System.out.print( array[dim - j - 1][dim - i - 1] + " " );
            }
            System.out.println();
        }
    

    变体 2

    使用一个循环提取所有对角线,但有额外的迭代一个额外的检查

        for( int k = 0 ; k < dim * 2 ; k++ ) {
            for( int j = 0 ; j <= k ; j++ ) {
                int i = k - j;
                if( i < dim && j < dim ) {
                    System.out.print( array[i][j] + " " );
                }
            }
            System.out.println();
        }
    

    输出:

    A B C D E 
    F G H I J 
    K L M N O 
    P Q R S T 
    U V W X Y 
    ============================
    A 
    F B 
    K G C 
    P L H D 
    U Q M I E 
    V R N J 
    W S O 
    X T 
    Y 
    

    更新

    cmets中有关于矩形矩阵(height != width)的问题。这是矩形矩阵的解决方案:

    规则保持不变:同一对角线上的元素索引之和是常数

    索引的最小总和是0(对于矩阵中索引为[0;0]的第一个元素)

    索引的最大总和为width + height - 2(对于索引为[height-1; with-1]的矩阵中的最后一个元素)

    初始化矩形矩阵仅用于测试目的:

        int WIDTH = 7;
        int HEIGHT = 3;
        char ch = 'A';
        String[][] array = new String[HEIGHT][];
        for( int i = 0 ; i < HEIGHT ; i++ ) {
            array[i] = new String[WIDTH];
            for( int j = 0 ; j < WIDTH ; j++, ch++ ) {
                array[i][j] = "" + ch;
            }
        }
    

    打印我们的矩形矩阵:

        for( int i = 0 ; i < HEIGHT ; i++ ) {
            for( int j = 0 ; j < WIDTH ; j++, ch++ ) {
                System.out.print( array[i][j] + " " );
            }
            System.out.println();
        }
        System.out.println( "============================" );
    

    解决方案

        for( int k = 0 ; k <= WIDTH + HEIGHT - 2; k++ ) {
            for( int j = 0 ; j <= k ; j++ ) {
                int i = k - j;
                if( i < HEIGHT && j < WIDTH ) {
                    System.out.print( array[i][j] + " " );
                }
            }
            System.out.println();
        }
    

    输出:

    A B C D E F G 
    H I J K L M N 
    O P Q R S T U 
    ============================
    A 
    H B 
    O I C 
    P J D 
    Q K E 
    R L F 
    S M G 
    T N 
    U 
    

    【讨论】:

    • 是的,但是如果你有一个高度 != 宽度的矩阵,你会怎么做。除了他的代码暗示它之外,我实际上并没有看到原文中的要求,但他的代码暗示你应该使用 i 和 j 而不是 j 和 k 循环数组。随便吧。
    • 对于变体 2,有很多额外的情况。将dim * 2 更改为dim * 2 - 1 将解决其中一个问题。
    • 矩形可以吗?
    • @Tata​​rize, @"Сергей Грушин",请查看我对矩形矩阵的更新,即高度!= 宽度
    • 完美运行! @user243872 将答案标记为已接受怎么样?
    【解决方案3】:

    代码如下:

    public void loopDiag(String [][] b) {
    
            boolean isPrinted  = false;
            for (int i = 0 ; i < b.length ; i++) {
                String temp="";
                int x=i;
                for(int j = 0 ; j < b.length ; j++) {
                    int y = j;
                    while (x >= 0 && y < b.length) {
                        isPrinted = false;
                        temp+=b[x--][y++];                  
                    }
                    if(!isPrinted) {
                        System.out.println(temp);
                        isPrinted = true;
                    }
                }
            }
        }
    

    【讨论】:

      【解决方案4】:
          String ar[][]={{"a","b","c"},{"d","e","f"},{"g","h","i"}};
          int size1=ar.length-1, size2=ar.length;
      
          for(int i=0; i<ar.length; i++)
          {   
              String a="";        
              for(int j=0, x=ar.length-1-i; j<ar.length-i; j++, x--)
              {
                  if((j+x)==size1)
                  a=a+ar[x][j];
              }
              size1--;
      
              System.out.println(a);
              a="";
              for(int j=i+1, x=ar.length-1; j<ar.length; j++, x--)
              {
                  if((j+x)==size2)
                  a=a+ar[x][j];
              }
              System.out.println(a);
              size2++;
          }
      

      输出

      gec 高频 D b 一世 一个

      【讨论】:

      • 您对元素进行了正确的分组,但将这些组返回到一个扭曲的序列中。请检查该组在问题中的正确位置。
      【解决方案5】:

      这是在 while 循环中打印对角矩阵的非常直观的方法。

      将问题概括为整体而不是两个部分,并在空间复杂度方面进行优化。

      package algorithm;
      
      public class printDiagonaly
      {
          public static void main(String[] args)
          {
              int[][] a = new int[][]{{1, 2, 3, 4, 5},
                      {6, 7, 8, 9, 10},
                      {11, 12, 13, 14, 15},
                      {16, 17, 18, 19, 20}};
      
              int lr = 0;
              int lc = -1;
              int fr = -1;
              int fc = 0;
              int row = a.length - 1;
              int col = a[0].length - 1;
      
              while (lc < col || fc < col || fr < row || lr < row)
              {
                  if (fr < row)
                  {
                      fr++;
                  }
                  else
                  {
                      fc++;
                  }
      
                  if (lc < col)
                  {
                      lc++;
                  }
                  else
                  {
                      lr++;
                  }
      
                  int tfr = fr;
                  int tlr = lr;
                  int tlc = lc;
                  int tfc = fc;
      
                  while (tfr >= tlr && tfc <= tlc)
                  {
      
                      System.out.print(a[tfr][tfc] + " ");
                      tfr--;
                      tfc++;
                  }
                  System.out.println("\n");
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        是这样的:

        int [][]mat = { {1,2,3},
                        {4,5,6},
                        {7,8,9},
        };
        
        int N=3;
        
        for (int s=0; s<N; s++) {
            for (int i=s; i>-1; i--) {
                System.out.print(mat[i][s-i] + " ");
            }
            System.out.println();
        }
        
        for (int s=1; s<N; s++) {
            for (int i=N-1; i>=s; i--) {
                System.out.print(mat[i][s+N-1-i] + " ");
            }
            System.out.println();
        }
        

        第一个循环打印从第一列开始的对角线,第二个循环打印剩余的对角线(从底行开始)。

        输出:

        1 
        4 2 
        7 5 3 
        8 6 
        9 
        

        【讨论】:

          【解决方案7】:

          如果我们将其分解为 2 个子问题,解决方案会容易得多:

          1. 找出每条对角线的起点。
          2. 给定对角线的起始索引,打印对角线。

            public void printMatrixDiagonals(int[][] matrix) {
            
                int c = 0;
                int count = matrix.length + matrix[0].length -1;
                int i = 0, j = 0;
                //There can be at most  m + n -1 diagonals to be printed
                while (c < count) {
                    //Start printing diagonals from i and j
                    printDiagonal(i, j, matrix);
                    if (i < matrix.length -1) {
                        //We increment row index until we reach the max number of rows
                        i++;
                    } else if (j < matrix[0].length - 1) {
                        //We are at maximum index of row; so its time to increment col index
                        //We increment column index until we reach the max number of columns
                        j++;
                    }
                    c++;
                }
            }
            

          打印对角线:请注意,每次我们开始打印每条对角线时,行的索引都应该递减,列的索引应该递增。所以给定每个对角线的起始索引,我们可以如下打印对角线:

          private void printDiagonal(int i, int j, int[][] m) {
              while (i >=0 && j< m[0].length ) {
                  System.out.print(m[i][j] + " ");
                  i--;
                  j++;
              }
              System.out.println("");
          }
          

          【讨论】:

            【解决方案8】:

            这与 leoflower 在此处发布的内容相同。为了更好地理解,我刚刚更改了变量名称。

            level = 表示正在打印的对角线的当前级别。例如:- level = 2 表示索引为 (0,2),(1,1),(2,0) 的对角线元素

            currDiagRowIndex = 表示当前正在打印的对角线的行索引

            currDiagColIndex = 表示当前正在打印的对角线的列索引

            void printMatrixDiagonal(int matrix[][], int endRowIndex, int endColIndex){
                for(int level = 0; level < endColIndex; level++){
                    for(int currDiagRowIndex = 0, currDiagColIndex = level; currDiagRowIndex < endRowIndex && currDiagColIndex >= 0 ; currDiagRowIndex++, currDiagColIndex--){
                        System.out.print(matrix[currDiagRowIndex][currDiagColIndex] + "  ");
                    }
                    System.out.println();
                }
            
                for(int level = 1; level < endRowIndex; level++){
                    for(int currDiagRowIndex = level, currDiagColIndex = endColIndex-1; currDiagRowIndex < endRowIndex && currDiagColIndex >= 0; currDiagRowIndex++, currDiagColIndex--){
                        System.out.print(matrix[currDiagRowIndex][currDiagColIndex]+ "  ");
                    }
                    System.out.println();
                }
            }
            

            输入:

            1 2 3 4 5 
            6 7 8 9 10
            11 12 13 14 15
            16 17 18 19 20
            21 22 23 24 25
            

            输出:

            1  
            2  6  
            3  7  11  
            4  8  12  16  
            5  9  13  17  21  
            10  14  18  22  
            15  19  23  
            20  24  
            25  
            

            【讨论】:

              【解决方案9】:

              正如 Alex 在这里提到的,您需要查看循环中的索引。 以下是我解决这个问题的方法。

              Input:         
              a b c    ----- (0,0) (0,1) (0,2)
              d e f    ----- (1,0) (1,1) (1,2)
              g h i    ----- (2,0) (2,1) (2,2)
              
              Output:
              a        ----- (0,0)
              b d      ----- (0,1) (1,0)
              c e g    ----- (0,2) (1,1) (2,0)
              f h      ----- (1,2) (2,1)
              i        ----- (2,2)
              
              public class PrintDiagonal{
              
                  public static void printDR(String[][] matrix, int rows, int cols){
                      for(int c=0; c < cols; c++){
                          for(int i=0, j=c; i< rows && j>=0;i++,j--){
                              System.out.print(matrix[i][j] +" ");
                           }
                           System.out.println();
                      }
              
                      for(int r =1; r < rows; r++){
                          for(int i =r, j= cols -1; i<rows && j>=0; i++,j--){
                              System.out.print(matrix[i][j] + " ");
                          }
                          System.out.println();
                      }
                  }
                  public static void main(String[] args){
                      String[][] matrix ={
                          {"a","b","c"},
                          {"d","e","f"},
                          {"g","h","i"}
                      };
              
                      int rows = matrix.length;
                      int columns = matrix[0].length; 
                      printDR(matrix ,rows, columns);
                  }
              }
              

              【讨论】:

                【解决方案10】:

                这适用于非方形数组。这很容易理解,但每个对角线调用一次 min() 和 max()。

                int ndiags = width +  height - 1;
                System.out.println("---");
                for (int diag = 0; diag < ndiags; diag++) {
                    int row_stop = Math.max(0,  diag -  width + 1);
                    int row_start = Math.min(diag, height - 1);
                    for (int row = row_start; row >= row_stop; row--) {
                        // on a given diagonal row + col = constant "diag"
                        // diag labels the diagonal number
                        int col = diag - row;
                        System.out.println(col + "," + row);
                        relax(col, row);
                    }
                    System.out.println("---");
                }
                

                这是宽度=3,高度=3的输出

                ---
                0,0
                ---
                0,1
                1,0
                ---
                0,2
                1,1
                2,0
                ---
                1,2
                2,1
                ---
                2,2
                ---
                

                宽度=3,高度=2

                ---
                0,0
                ---
                0,1
                1,0
                ---
                1,1
                2,0
                ---
                2,1
                ---
                

                宽度 = 2,高度 = 3

                ---
                0,0
                ---
                0,1
                1,0
                ---
                0,2
                1,1
                ---
                1,2
                ---
                

                【讨论】:

                • 太完美了!
                【解决方案11】:

                我写了以下代码。关键是用尽所有从顶部开始的对角线,然后移动到从侧面开始的对角线。我包括了一种方法,它结合了两个角度来遍历对角线西北 - 东南和东北 - 西南,以及用于遍历各个角度的独立方法。

                public static void main(String[] args){
                    int[][] m = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
                    printDiagonals(m, DiagonalDirection.NEtoSW, new DiagonalVisitor() {     
                        public void visit(int x, int y, int[][] m) {
                            System.out.println(m[x][y]);
                        }
                    });
                }
                
                public enum DiagonalDirection{
                    NWToSE,
                    NEtoSW
                }
                
                private static abstract class DiagonalVisitor{
                    public abstract void visit(int x, int y, int[][] m);
                }
                
                public static void printDiagonals(int[][] m, DiagonalDirection d, DiagonalVisitor visitor){
                
                    int xStart = d==DiagonalDirection.NEtoSW ? 0 : m.length-1;
                    int yStart = 1;
                
                
                    while(true){
                        int xLoop, yLoop;
                        if(xStart>=0 && xStart<m.length){
                            xLoop = xStart;
                            yLoop = 0;
                            xStart++;
                        }else if(yStart<m[0].length){
                            xLoop = d==DiagonalDirection.NEtoSW ? m.length-1 : 0;
                            yLoop = yStart;
                            yStart++;
                        }else
                            break;
                
                        for(;(xLoop<m.length && xLoop>=0)&&yLoop<m[0].length; xLoop=d==DiagonalDirection.NEtoSW ? xLoop-1 : xLoop+1, yLoop++){
                            visitor.visit(xLoop, yLoop, m);
                        }
                
                    }
                
                }
                
                public static void printDiagonalsNEtoSW(int[][] m, DiagonalVisitor visitor){
                
                    int xStart = 0;
                    int yStart = 1;
                
                
                    while(true){
                        int xLoop, yLoop;
                        if(xStart<m.length){
                            xLoop = xStart;
                            yLoop = 0;
                            xStart++;
                        }else if(yStart<m[0].length){
                            xLoop = m.length-1;
                            yLoop = yStart;
                            yStart++;
                        }else
                            break;
                
                        for(;xLoop>=0 && yLoop<m[0].length; xLoop--, yLoop++){
                            visitor.visit(xLoop, yLoop, m);
                        }
                
                
                    }
                }
                
                public static void printDiagonalsNWtoSE(int[][] m, DiagonalVisitor visitor){
                
                    int xStart = m.length-1;
                    int yStart = 1;
                
                
                    while(true){
                        int xLoop, yLoop;
                        if(xStart>=0){
                            xLoop = xStart;
                            yLoop = 0;
                            xStart--;
                        }else if(yStart<m[0].length){
                            xLoop = 0;
                            yLoop = yStart;
                            yStart++;
                        }else
                            break;
                
                        for(;xLoop<m.length && yLoop<m[0].length; xLoop++, yLoop++){
                            visitor.visit(xLoop, yLoop, m);
                        }       
                    }
                }
                

                【讨论】:

                  【解决方案12】:

                  自己动手,看看你需要循环的索引:

                  #1 (0,0)               -> a
                  #2 (1,0)  (0,1)        -> bd
                  #3 (2,0)  (1,1)  (0,2) -> gec
                  #4 (2,1)  (1,2)        -> hf
                  #5 (2,2)               -> i
                  

                  查看每次迭代中索引的变化并创建您的算法。没那么难,你自己做作业吧;)

                  【讨论】:

                  • 你真的改变了我看待问题的方法!写下索引可以很容易地提出解决方案
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-12-08
                  • 2018-01-21
                  • 1970-01-01
                  • 2020-05-15
                  • 1970-01-01
                  • 2020-10-08
                  • 1970-01-01
                  相关资源
                  最近更新 更多