web-dev-qa-db-ja.com

2次元配列を斜めにループ

配列の対角線の半分を歩くように次のコードを書きました。

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 
9
user243872

テスト目的でのみ配列を初期化します。

    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つのルールがあります-それらの合計は1つの対角で一定です。

バリアント1

2つのループを使用して、すべての対角線を抽出します。

最初のループは対角線の上半分を抽出します。

    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();
    }

2番目のループは、対角線の下半分で反復します。

    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

1つのループを使用してすべての対角線を抽出しますが、追加の反復1つの追加チェックがあります。

    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 

更新

コメントに長方形マトリックス(height!=width)に関する質問があります。長方形の行列のソリューションは次のとおりです。

ルールは同じままです:同じ対角線からの要素インデックスの合計は定数です

インデックスの最小合計はです(インデックス[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 
15
Nicolai

自分自身を助けて、ループする必要があるインデックスを見てください:

#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

各反復でのインデックスの変化を見て、アルゴリズムを作成します。それほど難しくはないので、宿題は自分で行ってください;)

5
alex

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("");
}
4
Big O

次のコードを書きました。重要なのは、上から始まるすべての対角線を使い果たしてから、両側から始まる対角線に移動することです。 2つの角度を組み合わせて対角線を北西-南東および北東-南西を横断する方法と、それぞれの角度を横断するスタンドアロンの方法を含めました。

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);
        }       
    }
}
3
AtlasMeh-ed

これは非正方形の配列で機能します。理解は簡単ですが、対角線ごとに1回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("---");
}

これは、width = 3、height = 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
---
2
Greg Whittier

これは、whileループで対角行列を出力する非常に直感的な方法です。

問題を2つの部分ではなく全体として一般化し、スペースの複雑さに関して最適化します。

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");
        }
    }
}
1
brahmananda Kar

こうやって:

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();
}

最初のループは最初の列から始まる対角線を印刷し、2番目のループは残りの対角線を印刷します(一番下の行から始まります)。

出力:

1 
4 2 
7 5 3 
8 6 
9 
0
Shubham Vadhera

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);
    }
}
0
leoflower
    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 hf db i a

0
Apurv Jaiswal

これがコードです:

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;
                }
            }
        }
    }
0
Aditya