Rotation d'une matrice NxN en Java

C'est une question de fissurer le Codage Interview. La solution dit que le programme fait tourner les bords extérieurs, puis les bords intérieurs. Cependant, j'ai du mal à suivre la logique des deux boucles for.

Quelqu'un Pourrait expliquer la logique du code (par exemple, pourquoi ils ne "couche haut" et "bas -> gauche", etc)? Sur une note de côté, comment serait le processus de réflexion lors d'une entrevue de codage?

Étant donné une image représentée par une matrice NxN, où chaque pixel l'image est de 4 octets, écrire une méthode pour faire pivoter l'image de 90 degrés. Pouvez-vous le faire en place?

public static void rotate(int[][] matrix, int n) {
    for (int layer = 0; layer < n / 2; ++layer) {
        int first = layer;
        int last = n - 1 - layer;
        for(int i = first; i < last; ++i) {
            int offset = i - first;
            int top = matrix[first][i]; // save top

            // left -> top
            matrix[first][i] = matrix[last-offset][first];          

            // bottom -> left
            matrix[last-offset][first] = matrix[last][last - offset]; 

            // right -> bottom
            matrix[last][last - offset] = matrix[i][last]; 

            // top -> right
            matrix[i][last] = top; // right <- saved top
        }
    }
}
23
demandé sur JGY 2014-09-17 08:47:48

8 réponses

Vue d'ensemble

Considérons une matrice d'échantillon pourrait ressembler à ceci:

ABCD
EFGH
IJKL
MNOP

Aux fins de mon explication, ABCD est considéré comme la ligne 0, EFGH est la ligne 1, et ainsi de suite. Le premier pixel de la ligne 0 est A.

Aussi, quand je parle de la coque extérieure, je fais référence à:

ABCD
E  H
I  L
MNOP

Regardons D'abord le code qui déplace les valeurs.

    int top = matrix[first][i]; // save top

La première ligne met en cache la valeur dans la position supérieure. Cela fait référence à la position sur le rangée supérieure de la matrice identifiée par [first] [i]. Par exemple: enregistrer le A.

    // left -> top
    matrix[first][i] = matrix[last-offset][first];          

La partie suivante déplace la valeur de la position gauche vers la position supérieure. Par exemple: prendre le M et le mettre où le A est.

    // bottom -> left
    matrix[last-offset][first] = matrix[last][last - offset]; 

La partie suivante déplace la valeur de la position inférieure vers la position gauche. Par exemple: prendre le P et le mettre où le M est.

    // right -> bottom
    matrix[last][last - offset] = matrix[i][last]; 

La partie suivante déplace la valeur de la position droite vers la position inférieure. Par exemple: la prise de la {[15] } et le mettre où le P est.

    // top -> right
    matrix[i][last] = top; // right <- saved top

La dernière partie déplace la valeur du cache (quelle était la position supérieure) dans la bonne position. Par exemple: mettre le A de la première étape où le D est.

Suivant les boucles.

La boucle externe va de la ligne 0 à la moitié du nombre total de lignes. C'est parce que lorsque vous faites pivoter la ligne 0, il tourne également la dernière ligne et lorsque vous faites pivoter la ligne 1, il tourne également dans l'avant-dernière ligne, et ainsi de sur.

La boucle interne va de la première position de pixel (ou colonne) de la ligne à la dernière. Gardez à l'esprit que pour la ligne 0, Il s'agit du pixel 0 au dernier pixel, mais pour la ligne 1, Il s'agit du pixel 1 à l'avant-dernier pixel, puisque le premier et le dernier pixel sont pivotés dans le cadre de la ligne 0.

Ainsi, la première itération de la boucle externe fait tourner la coque externe. En d'autres termes:

ABCD
EFGH
IJKL
MNOP

Devient:

MIEA
NFGB
OJKC
PLHD

Voyez comment la coque extérieure a tourné dans le sens des aiguilles d'une montre, mais le noyau interne n'a pas bougé.

Ensuite, la deuxième itération de la boucle externe fait tourner la deuxième ligne (à l'exclusion des premier et dernier pixels) et nous nous retrouvons avec:

MIEA
NJFB
OKGC
PLHD
36
répondu Jason 2014-09-17 05:20:55

J'écris cette réponse parce que même après avoir lu la réponse Postée par Jason ci-dessus (c'est bien et a résolu quelques questions que j'avais), il n'était toujours pas clair pour moi quel rôle est variable "offset" jouer dans cette logique, donc passer quelques heures à comprendre cela, j'ai pensé à le partager avec tout le monde.

Il y a beaucoup de variables utilisées ici et il est important de comprendre la signification de chacune.

Si vous regardez la variable 'first', c'est inutile, c'est essentiellement, la "couche" elle-même, "first" n'est pas modifiée du tout dans toute la logique. J'ai donc supprimé la variable' first ' (et cela fonctionne, lisez à l'avance).

Pour comprendre comment chacun de ces valeurs changent à chaque itération de la boucle intérieure que j'ai imprimé les valeurs de ces variables. Jetez un oeil à la sortie et comprenez quelles valeurs changent lorsque nous passons d'un coin à l'autre dans la boucle for interne, quelles valeurs restent constantes tout en traversant une seule couche et quelles valeurs changent seulement quand nous changeons la couche.

Une itération de boucle interne déplace un seul bloc. Nombre d'itérations nécessaires pour déplacer une seule couche va changer que nous allons vers l'intérieur. La variable 'last' fait ce travail pour nous, elle restreint la boucle interne (restreint la couche interne et nous empêche d'aller au-delà du shell, en s'appuyant sur la nomenclature utilisée par Jason)

Il est temps d'étudier la sortie .

J'ai utilisé la matrice 6x6.

Input: 

 315 301 755 542 955 33
 943 613 233 880 945 280
 908 609 504 61 849 551
 933 251 706 707 913 917
 479 785 634 97 851 745
 472 348 104 645 17 273

--------------Starting an iteration of OUTER FOR LOOP------------------

--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =0
buffer = 315
offset = i-layer = 0
Current Status: 

 472 301 755 542 955 315
 943 613 233 880 945 280
 908 609 504 61 849 551
 933 251 706 707 913 917
 479 785 634 97 851 745
 273 348 104 645 17 33
--------------Finished an iteration of inner for loop------------------

--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =1
buffer = 301
offset = i-layer = 1
Current Status: 

 472 479 755 542 955 315
 943 613 233 880 945 301
 908 609 504 61 849 551
 933 251 706 707 913 917
 17 785 634 97 851 745
 273 348 104 645 280 33
--------------Finished an iteration of inner for loop------------------

--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =2
buffer = 755
offset = i-layer = 2
Current Status: 

 472 479 933 542 955 315
 943 613 233 880 945 301
 908 609 504 61 849 755
 645 251 706 707 913 917
 17 785 634 97 851 745
 273 348 104 551 280 33
--------------Finished an iteration of inner for loop------------------

--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =3
buffer = 542
offset = i-layer = 3
Current Status: 

 472 479 933 908 955 315
 943 613 233 880 945 301
 104 609 504 61 849 755
 645 251 706 707 913 542
 17 785 634 97 851 745
 273 348 917 551 280 33
--------------Finished an iteration of inner for loop------------------

--------------Starting an iteration of inner for loop------------------
layer =0
last =5
i =4
buffer = 955
offset = i-layer = 4
Current Status: 

 472 479 933 908 943 315
 348 613 233 880 945 301
 104 609 504 61 849 755
 645 251 706 707 913 542
 17 785 634 97 851 955
 273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Finished an iteration of OUTER FOR LOOP------------------

--------------Starting an iteration of OUTER FOR LOOP------------------

--------------Starting an iteration of inner for loop------------------
layer =1
last =4
i =1
buffer = 613
offset = i-layer = 0
Current Status: 

 472 479 933 908 943 315
 348 785 233 880 613 301
 104 609 504 61 849 755
 645 251 706 707 913 542
 17 851 634 97 945 955
 273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------

--------------Starting an iteration of inner for loop------------------
layer =1
last =4
i =2
buffer = 233
offset = i-layer = 1
Current Status: 

 472 479 933 908 943 315
 348 785 251 880 613 301
 104 609 504 61 233 755
 645 97 706 707 913 542
 17 851 634 849 945 955
 273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------

--------------Starting an iteration of inner for loop------------------
layer =1
last =4
i =3
buffer = 880
offset = i-layer = 2
Current Status: 

 472 479 933 908 943 315
 348 785 251 609 613 301
 104 634 504 61 233 755
 645 97 706 707 880 542
 17 851 913 849 945 955
 273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Finished an iteration of OUTER FOR LOOP------------------

--------------Starting an iteration of OUTER FOR LOOP------------------

--------------Starting an iteration of inner for loop------------------
layer =2
last =3
i =2
buffer = 504
offset = i-layer = 0
Current Status: 

 472 479 933 908 943 315
 348 785 251 609 613 301
 104 634 706 504 233 755
 645 97 707 61 880 542
 17 851 913 849 945 955
 273 745 917 551 280 33
--------------Finished an iteration of inner for loop------------------
--------------Finished an iteration of OUTER FOR LOOP------------------

 472 479 933 908 943 315
 348 785 251 609 613 301
 104 634 706 504 233 755
 645 97 707 61 880 542
 17 851 913 849 945 955
 273 745 917 551 280 33

Désolé mais il n'y a pas d'autre moyen que de réfléchissez à la façon dont les valeurs de la couche, i et offset changent pour comprendre ce qui se passe ici.

Enfin, le code

Voici le code où j'ai supprimé inutile en premier et ajouté toutes les instructions d'impression, au cas où quelqu'un voudrait jouer plus. Ce code a également une initialisation et une impression de matrice aléatoires:

package com.crackingthecodinginterview.assignments.chap1;

public class Problem6RotateMatrix90 {

    public static void main(String args[]){
        int[][] matrix = new int[6][6];
        initializeMatrix(matrix,6);
        System.out.println("Input: ");
        printMatrix(matrix,6);
        rotate(matrix,6);
        printMatrix(matrix,6);
    }

    public static void rotate(int[][] matrix, int n) {
        for (int layer = 0; layer < n / 2; ++layer) {
            System.out.println("\n--------------Starting an iteration of OUTER FOR LOOP------------------");

            int last = n - 1 - layer;
            for(int i = layer; i < last; ++i) {
                int offset = i - layer;
                int buffer = matrix[layer][i]; // save top
                System.out.println("\n--------------Starting an iteration of inner for loop------------------");
                System.out.println("layer ="+layer);

                System.out.println("last ="+last);
                System.out.println("i ="+i);

                System.out.println("buffer = "+buffer);
                System.out.println("offset = i-layer = "+ offset);

                // left -> top
                matrix[layer][i] = matrix[last-offset][layer];          

                // bottom -> left
                matrix[last-offset][layer] = matrix[last][last - offset]; 

                // right -> bottom
                matrix[last][last - offset] = matrix[i][last]; 

                // top -> right
                matrix[i][last] = buffer; // right <- saved top

                //print
                System.out.println("Current Status: ");
                printMatrix(matrix,6);
                System.out.println("--------------Finished an iteration of inner for loop------------------");
            }
            System.out.println("--------------Finished an iteration of OUTER FOR LOOP------------------");

        }
    }

    public static void printMatrix(int[][] matrix,int n){
        System.out.print("\n");
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                System.out.print(" "+matrix[i][j]);
            }
            System.out.print("\n");
        }
    }

    public static void initializeMatrix(int[][] matrix,int n){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                matrix[i][j]=(int) (Math.random() * 1000);
            }
        }
    }

}
4
répondu Saurabh Patil 2018-09-30 03:26:27

Juste vu qu'il existe un moyen plus simple d'écrire le code en refactorisant "Last-offset":

  public static void rotateInPlace90DegreesClockwise(int[][] matrix) {
      int n = matrix.length;
      int half = n / 2;

      for (int layer = 0; layer < half; layer++) {
          int first = layer;
          int last = n - 1 - layer;

          for (int i = first; i < last; i++) {
              int offset = i - first;
              int j = last - offset;
              int top = matrix[first][i]; // save top

              // left -> top
              matrix[first][i] = matrix[j][first];          

              // bottom -> left
              matrix[j][first] = matrix[last][j]; 

              // right -> bottom
              matrix[last][j] = matrix[i][last]; 

              // top -> right
              matrix[i][last] = top; // right <- saved top
          }
      }
  }
2
répondu Lau Chok Sheak 2015-05-25 15:46:49

Vérifiez cette solution pour le faire en place.

public void rotateMatrix(Pixel[][] matrix) {

    for (int i = 0; i < matrix.length / 2; i++) {

        for (int j = 0; j < matrix.length - 1 - 2 * i; j++) {
            Pixel tmp = matrix[j + i][matrix.length - 1 - i];
            matrix[j + i][matrix.length - 1 - i] = matrix[i][j + i];
            matrix[i][j + i] = matrix[matrix.length - 1 - j - i][i];
            matrix[matrix.length - 1 - j - i][i] = matrix[matrix.length - 1 - i][matrix.length - 1 - j - i];
            matrix[matrix.length - 1 - i][matrix.length - 1 - j - i] = tmp;
        }
    }
}
2
répondu Andrew B. 2016-08-29 18:07:56

La solution Simple est:

int[][] a = { {00,01,02  }, { 10,11,12} ,{20,21,22}};
System.out.println(" lenght " + a.length);

int l = a.length;

for (int i = 0; i <l; i++) {

    for (int j = l - 1; j >= 0; j--) {
        System.out.println(a[j][i]);
    }
}
0
répondu saritha kota 2015-10-27 09:53:06
  /**
 * @param args
 */
public static void main(String[] args) {
    int n = 5; //5x5 matrix
    int[][] matrixInitial = initMatrix(n);
    int[][] matrixFinal = rotate(matrixInitial, n);
    System.out.println(matrixFinal.length);

    int m = 4; //4x4 matrix
    int[][] matrixInitial2 = initMatrix(m);
    int[][] matrixFinal2 = rotate(matrixInitial2, m);
    System.out.println(matrixFinal2.length);
}

private static int[][] rotate(int[][] matrixInitial, int n) {
//it is much like square layers. each layer will be read and rotated
    int layerCount = (n + 1) / 2; 
    System.out.println("n: " + n + " layerCount: " + layerCount);
    int[][] matrixFinal = new int[n][n];
    if (n % 2 == 1) { // for odd # layers the centre does not move
        matrixFinal[n / 2][n / 2] = matrixInitial[n / 2][n / 2];
        layerCount -= 1;
    }

    for (int i = 0; i < layerCount; i++) {
        int width = n - (2 * i); // width of the layer
        System.out.println("width: " + width);
        int[] top = new int[width]; // read top
        for (int j = 0; j < width; j++) {
            top[j] = matrixInitial[i][i + j];
        }
        System.out.println("top: " + Arrays.toString(top));

        //OK TOP TO RIGHT

        for (int j = 0; j < width; j++) { // move top to right 
            matrixFinal[j+i][width-1+i] = top[j];
        }

        int[] tempLeft = new int[width]; // left will be read backwards
        for (int j = 0; j < width; j++) { // reverse the temp
            tempLeft[j] = matrixInitial[i + j][i];
        }

        int[] left = new int[width];
        int indexTemp = 0;
        for (int j = width-1; j >= 0; j--) { // move temp to left
            left[indexTemp++] = tempLeft[j];
        }
        System.out.println("left: " + Arrays.toString(left));

        //OK LEFT TO TOP

        for (int j = 0; j < width; j++) { // move left to top
            matrixFinal[i][j + i] = left[j];
        }

        int[] bottom = new int[width]; read bottom
        for (int j = 0; j < width; j++) {
            bottom[j] = matrixInitial[width - 1 + i][j + i];
        }
        System.out.println("bottom: " + Arrays.toString(bottom));

        //OK BOTTOM TO LEFT

        for (int j = 0; j < width; j++) { // move bottom to left
            matrixFinal[j+i][i] = bottom[j];
        }

        int[] tempRight = new int[width]; // right will be read backwards
        for (int j = 0; j < width; j++) {
            tempRight[j] = matrixInitial[j + i][width - 1 + i];
        }
        int[] right = new int[width]; //reverse the temp
        int indexTemp2 = 0;
        for (int j = width; j > 0; j--) {
            right[indexTemp2++] = tempRight[j - 1];
        }
        System.out.println("right: " + Arrays.toString(right));

        //OK RIGHT TO BOTTOM
        for (int j = 0; j < width; j++) { // move right to bottom
            matrixFinal[width-1+i][j + i] = right[j];
        }

    }
    for (int i = 0; i < n; i++) {
        System.out.println(Arrays.toString(matrixFinal[i]));
    }
    return matrixFinal;
}

private static int[][] initMatrix(int n) { // init the matrix
    int[][] matrix = new int[n][n];
    int fill = 0;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            matrix[i][j] = fill++;
        }
    }

    for (int i = 0; i < n; i++) {
        System.out.println(Arrays.toString(matrix[i]));
    }
    System.out.println("******");
    return matrix;
}
0
répondu user3743369 2017-01-12 16:46:38

Voici ma solution en JavaScript, elle échange des valeurs entre une ligne et une colonne à partir du bord supérieur droit, allant vers l'intérieur jusqu'à ce que la paire inférieure à gauche soit échangée.

function rotateMatrix(arr) {
    var n = arr.length - 1;

    for (var i = 0; i < n; i++) {
        for (var j = 0; j < n - i; j++) {
            var temp = arr[i][j];

            arr[i][j] = arr[n - j][n - i]; // top row
            arr[n - j][n - i] = temp; // right column
        }
    }

    return arr;
}
0
répondu George Kagan 2017-04-12 18:40:13

Voici une solution simple qui fonctionne parfaitement pour moi.

 private int[][] rotateMatrix(int[][] matrix)
    {
        for(int i=0;i<matrix.length-1;i++)
        {
            for(int j =i;j<matrix[0].length;j++)
            {
                if(i!=j) {
                    int temp = matrix[i][j];
                    matrix[i][j] = matrix[j][i];
                    matrix[j][i] = temp;
                }
            }
        }
        return matrix;
    }
0
répondu CodeNinja 2017-05-20 17:11:30