2014-09-17 19 views
20

Dies ist eine Frage von Cracking the Coding Interview. Die Lösung besagt, dass das Programm die Außenkanten und dann die Innenkanten dreht. Ich habe jedoch Probleme, die Logik der beiden For-Schleifen zu folgen.Rotieren einer NxN-Matrix in Java

Könnte jemand die Logik des Codes erklären (z. B. warum sie "Schicht < n/2" und die vier Schritte "links -> oben" und "unten -> links" usw.)? Nebenbei bemerkt, wie wäre der eigene Denkprozess bei einem Coding-Interview?

durch eine NxN-Matrix dargestellt ein Bild gegeben, wobei jedes Pixel in dem Bild 4 Bytes ist, schreiben, ein Verfahren, das Bild um 90 Grad zu drehen. Können Sie dies an Ort und Stelle tun?

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 
     } 
    } 
} 

Antwort

32

Übersicht

einer Probenmatrix Betrachten Sie könnte wie folgt aussehen:

ABCD 
EFGH 
IJKL 
MNOP 

Für die Zwecke meiner Erklärung wird ABCD betrachtet als Zeile 0, ist EFGH Reihe 1 , und so weiter. Das erste Pixel der Zeile 0 A.

Auch, wenn ich über die äußere Schale zu sprechen, ich beziehe mich auf:

ABCD 
E H 
I L 
MNOP 

Zuerst auf den Code schauen wir uns, dass die Werte bewegt.

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

Die erste Zeile speichert den Wert in der oberen Position. Dies bezieht sich auf die Position in der obersten Zeile der Matrix, die mit [first] [i] gekennzeichnet ist. ZB: Speichern der A.

Der nächste Teil verschiebt den Wert von der linken Position in die oberste Position. ZB: nimm die M und setze sie wo die A ist.

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

Der nächste Teil verschiebt den Wert von der unteren Position in die linke Position. ZB: nimm die P und setze sie wo die M ist.

Der nächste Teil verschiebt den Wert von der richtigen Position in die untere Position. ZB: Nehmen Sie die D und setzen Sie es wo die P ist.

Der letzte Teil verschiebt den Wert aus dem Cache (was die oberste Position war) in die richtige Position. ZB: Setzen Sie die A von der ersten Stufe, wo die ist.

Als nächstes die Schleifen.

Die äußere Schleife läuft von Zeile 0 bis zur Hälfte der Gesamtzahl der Zeilen. Dies liegt daran, dass beim Drehen von Zeile 0 auch die letzte Zeile gedreht wird und wenn Sie Zeile 1 drehen, wird auch die vorletzte Zeile usw. rotiert.

Die innere Schleife läuft von der ersten Pixelposition (oder Spalte) in der Zeile bis zur letzten. Beachten Sie, dass dies für Zeile 0 von Pixel 0 bis zum letzten Pixel ist, aber für Zeile 1 von Pixel 1 bis zum vorletzten Pixel, da das erste und das letzte Pixel als Teil von Zeile 0 gedreht werden .

So die erste Iteration der äußeren Schleife macht die äußere Schale drehen. Mit anderen Worten:

ABCD 
EFGH 
IJKL 
MNOP 

wird:

MIEA 
NFGB 
OJKC 
PLHD 

Sehen Sie, wie die Außenschale im Uhrzeigersinn gedreht hat, aber der innere Kern nicht bewegt hat.

Dann wird die zweite Iteration der äußeren Schleife bewirkt, dass die zweite Reihe drehen (den ersten und letzten Pixel ausgenommen), und wir am Ende mit:

MIEA 
NJFB 
OKGC 
PLHD 
+1

Vielen Dank für die schnelle Antwort innerhalb, Ihre Erklärung wird sehr geschätzt. Ich entschuldige mich, wenn diese Frage zu einfach ist, aber ich hatte Schwierigkeiten, in einem größeren Maßstab zu verstehen, was "links", "rechts", "oben" und "unten" waren und woraus eine "Schicht" besteht. Wären links, rechts, oben, unten nur die Eckstücke? Wäre jede Schicht nur eine Grenze des nach innen gehenden Quadrats? – JGY

+0

Ich werde meine Antwort bearbeiten ... – Jason

+0

@Jason Danke für die Erklärung. Ich kann die Logik hinter "int offset = i - first" nicht verstehen. in der inneren Schleife. – Ayusman

2

Gerade gesehen, dass es eine einfachere Art und Weise ist die schreiben Code durch Refactoring „liest - 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 
      } 
     } 
    } 
+0

Kannst du das bitte erklären? Was ist die Logik? –

2

ich schreibe diese Antwort, weil auch nach der von Jason gepostet Antwort liest oben (es ist schön und ein paar Fragen haben löste ich hatte) war es noch nicht Klar für mich, welche Rolle der variable Offset in dieser Logik spielt, also ein Couple Um das zu verstehen, dachte ich, es mit allen zu teilen.

Es gibt viele Variablen hier verwendet und es ist wichtig, die Bedeutung von jedem zu verstehen.

Wenn man sich die Variable 'first' anschaut, ist sie nutzlos, sie ist im Grunde die 'Schicht' selbst, 'first' wird in der gesamten Logik überhaupt nicht verändert. Also habe ich 'erste' Variable entfernt (und es funktioniert, lesen Sie weiter).

Um zu verstehen, wie sich jeder dieser Werte in jeder Iteration der inneren for-Schleife ändert, habe ich die Werte dieser Variablen ausgedruckt. Sehen Sie sich die Ausgabe an und verstehen Sie, welche Werte sich ändern, wenn wir uns in der inneren for-Schleife von einer Ecke zur nächsten bewegen. Diese Werte bleiben konstant, während wir eine einzelne Ebene durchlaufen und welche Werte sich nur ändern, wenn wir die Ebene ändern.

Eine Iteration der inneren Schleife verschiebt einen einzelnen Block. Die Anzahl der Iterationen, die benötigt werden, um eine einzelne Ebene zu verschieben, ändert sich, wenn wir nach innen gehen. Die Variable ‚last‘ macht diesen Job für uns, es die innere Schleife begrenzt (beschränkt die innere Schicht & uns hält von jenseits der Schale gehen, aufbauend auf der Nomenklatur Jason verwendet)

Zeit die Ausgabe zu studieren.

Ich habe 6x6 Matrix verwendet.

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 

Sorry, aber es gibt keinen anderen Weg, als auf, darüber nachzudenken, wie die Werte der Schicht, i und Offset-Änderung zu verstehen, was zum Teufel hier geschieht.

Schließlich wird der Code

Hier ist der Code, wo ich unnötig zuerst entfernt und hinzugefügt, um die alle print-Anweisungen, im Falle, wenn jemand will, mehr spielen.Dieser Code hat auch Zufallsmatrix Initialisierung und Druck:

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

} 
0

Die einfache Lösung ist:

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]); 
    } 
} 
+1

Dies dreht die Matrix nicht. Es druckt nur die gedrehte Form der Matrix. – TheHardRock

2

Check diese Lösung es an Ort und Stelle zu tun.

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; 
     } 
    } 
} 
0
/** 
* @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

Hier ist meine Lösung in JavaScript, es Werte zwischen einer Reihe Swaps und eine Spalte aus der oberen rechten Rand ausgehend nach innen gehen, bis der Boden-Paar am weitesten links vertauscht wird.

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

Hier ist eine einfache Lösung, die perfekt für mich funktioniert.

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

Dies transponiert die Matrix; es dreht es nicht. Bei der transponierten Matrix müssten Sie jede Zeile umkehren, um die korrekte gedrehte Matrix zu erhalten. – jagthebeetle