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