una tamaño rotar rotacion maximo matriz matrices izquierda grados girar cual con arreglo array java matrix rotational-matrices

tamaño - rotar un arreglo en java



Girar una matriz NxN en Java (8)

Esta es una pregunta de Cracking the Coding Interview. La solución dice que el programa gira los bordes exteriores, luego los bordes interiores. Sin embargo, tengo problemas para seguir la lógica de los bucles for.

¿Podría alguien explicar la lógica del código (por ejemplo, por qué lo hacen "capa <n / 2" y los cuatro pasos de "izquierda -> arriba" y "abajo -> izquierda", etc.)? En una nota al margen, ¿cómo sería el proceso de pensamiento cuando se presente esto durante una entrevista de codificación?

Dada una imagen representada por una matriz NxN, donde cada píxel de la imagen tiene 4 bytes, escriba un método para girar la imagen 90 grados. ¿Puedes hacer esto en su lugar?

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


Acabo de ver que hay una manera más simple de escribir el código refactorizando "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 } } }


Aquí está mi solución en JavaScript, intercambia valores entre una fila y una columna comenzando desde el borde superior derecho, yendo hacia adentro hasta que se intercambie el par inferior-más oscuro.

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


Aquí hay una solución simple que funciona perfectamente para mí.

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


Estoy escribiendo esta respuesta porque incluso después de leer la respuesta publicada por Jason (es agradable y resolvió un par de preguntas que tenía) todavía no estaba claro para mí cuál es el papel que desempeña la compensación variable en esta lógica, por lo que gasto un un par de horas para entender esto, pensé en compartirlo con todos.

Aquí se usan muchas variables y es importante comprender la importancia de cada una.

Si miras la variable ''primero'', es inútil, es esencialmente la ''capa'' en sí misma, ''primero'' no se modifica en absoluto en toda la lógica. Así que he eliminado la ''primera'' variable (y funciona, lea adelante).

Para comprender cómo cada uno de estos valores cambia en cada iteración del ciclo for interno, he impreso los valores de estas variables. Eche un vistazo a la salida y comprenda qué valores cambian cuando nos movemos de una esquina a otra en el ciclo for interno, cuyos valores permanecen constantes al atravesar una sola capa y qué valores cambian solo cuando cambiamos la capa.

Una iteración del bucle interno mueve un solo bloque. El número de iteraciones necesarias para mover una sola capa cambiará a medida que avancemos. La variable ''last'' hace ese trabajo por nosotros, restringe el bucle interno (restringe la capa interna y nos impide ir más allá del caparazón, basándose en la nomenclatura utilizada por Jason)

Tiempo para estudiar la salida .

He usado matriz 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

Lo siento, pero no hay otra manera que reflexionar sobre cómo cambian los valores de layer, i y offset para entender qué diablos está pasando aquí.

Finalmente el código

Este es el código donde quité innecesario primero y agregué todas las declaraciones de impresión, en caso de que alguien quiera jugar más. Este código también tiene inicialización e impresión de matrices aleatorias:

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


La solución simple es:

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


verifique esta solución para hacerlo en su lugar.

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


Visión de conjunto

Considere una matriz de muestra podría verse así:

ABCD EFGH IJKL MNOP

A los efectos de mi explicación, ABCD se considera como la fila 0, EFGH es la fila 1, y así sucesivamente. El primer píxel de la fila 0 es A.

Además, cuando hablo del caparazón exterior, me refiero a:

ABCD E H I L MNOP

Primero veamos el código que mueve los valores.

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

La primera línea almacena en caché el valor en la posición superior. Esto se refiere a la posición en la fila superior de la matriz identificada por [primera] [i]. Por ejemplo: guardar el A

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

La siguiente parte mueve el valor de la posición izquierda a la posición superior. Ej .: tomar la M y ponerla donde está la A

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

La siguiente parte mueve el valor desde la posición inferior a la posición izquierda. Por ejemplo: tomando la P y poniéndola donde está la M

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

La siguiente parte mueve el valor desde la posición correcta a la posición inferior. Ej .: tomar la D y ponerla donde está la P

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

La última parte mueve el valor de la memoria caché (que era la posición superior) a la posición correcta. Ej .: poner la A desde el primer paso donde está la D

Siguiente los bucles.

El bucle externo se extiende desde la fila 0 hasta la mitad del número total de filas. Esto se debe a que cuando gira la fila 0, también gira la última fila y cuando gira la fila 1, también gira la penúltima fila, y así sucesivamente.

El bucle interno se ejecuta desde la primera posición de píxel (o columna) en la fila hasta la última. Tenga en cuenta que para la fila 0, esto es desde el píxel 0 hasta el último píxel, pero para la fila 1, esto es desde el píxel 1 hasta el penúltimo píxel, ya que el primer y el último píxel se rotan como parte de la fila 0 .

Entonces, la primera iteración del bucle externo hace que la cubierta externa gire. En otras palabras:

ABCD EFGH IJKL MNOP

se convierte en:

MIEA NFGB OJKC PLHD

Vea cómo la capa externa ha girado en el sentido de las agujas del reloj, pero el núcleo interno no se ha movido.

Luego, la segunda iteración del bucle externo hace que la segunda fila gire (excluyendo el primer y último pixel) y terminamos con:

MIEA NJFB OKGC PLHD


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