问题
I'm trying to go over the problems in the Cracking the Coding Interview book. One of the questions asks me to rotate a matrix 90 degrees clockwise. Now, while trying to solidify my understanding of matrix rotation, I tried to embark on a new problem: to try to rotate a matrix 90 degrees counterclockwise (the other direction).
I've tried to go through layers of a square matrix, the outer layer, iterating all the way into the inner layer and rotating all the indexes of each side of the "square" one by one. This basically is what Gayle Laakman McDowell's solution implemented, but the other direction.
public static void rotateMatrix(int[][] matrix) {
if (matrix.length == 0) {
return;
}
for (int i = 0; i < matrix.length / 2; i++) {
int top = i;
int bottom = matrix.length - 1 - i;
for (int j = top; j < bottom; j++) {
int temp = matrix[top][j];
matrix[top][j] = matrix[j][matrix.length - 1 - j];
matrix[j][matrix.length - 1 - j] = matrix[bottom][j];
matrix[bottom][j] = matrix[j][matrix.length - 1 - bottom];
matrix[j][matrix.length - 1 - bottom] = temp;
}
}
}
I expected the result of a sample matrix
[1,2,3]
[4,5,6]
[7,8,9]
to be
[3,6,9]
[2,5,8]
[1,4,7]
but my code resulted in
[1,5,7]
[2,8,6]
[3,4,9]
Where is the flaw/discrepancy in my code?
回答1:
If you draw out the matrix to visualize, you'll see that some of your indices are off. For example, instead of using matrix.length-1
, you should use bottom in your updates because the size of the layer's square will decrease as i
increases. Another error is that in your second update, you should have:
matrix[j][bottom] = matrix[bottom][bottom - (j - top)];
instead of:
matrix[j][bottom] = matrix[bottom][j];
This is because in the bottom row of the layer the indices start from the last column and move backward to the first column. j - top
indicates how far along you are in the top row of your layer.
After drawing out the matrix, I found the correct updates to be as follows:
public static void main(String[] args) {
int n = 5;
int[][] a = new int[n][n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
a[i][j] = i * n + j + 1;
}
}
rotateMatrix(a);
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[0].length; j++) {
System.out.printf("%3d", a[i][j]);
}
System.out.println();
}
}
public static void rotateMatrix(int[][] matrix) {
if (matrix.length == 0) {
return;
}
for (int i = 0; i < matrix.length / 2; i++) {
int top = i;
int bottom = matrix.length - 1 - i;
for (int j = top; j < bottom; j++) {
int temp = matrix[top][j];
matrix[top][j] = matrix[j][bottom];
matrix[j][bottom] = matrix[bottom][bottom - (j - top)];
matrix[bottom][bottom - (j - top)] = matrix[bottom - (j - top)][top];
matrix[bottom - (j - top)][top] = temp;
}
}
}
Output:
5 10 15 20 25
4 9 14 19 24
3 8 13 18 23
2 7 12 17 22
1 6 11 16 21
回答2:
You're working on a single matrix instance, setting values in your matrix while also reading the old values which likely is causing your problem.
Making the function return a new matrix would make your job easier. Your code could then be:
public static int[][] rotateMatrix(int[][] m) {
if(m.length == 0) return new int[0][0];
int rows = m.length, cols = m[0].length;
int[][] result = new int[cols][rows];
for(int row = 0; row < cols; row++) {
for(int col = 0; col < rows; col++) {
result[row][col] = m[col][rows - row - 1];
}
}
return result;
}
I would also encapsulate the int[][]
array in a class to enforce immutability.
回答3:
Rotating the matrix 90 degrees is similar to transposing. The indices of [i][j]
become [j][i]
, but the indices of one of its sides becomes equal to the length of the side, minus 1, minus the current index of the side
. Indexes start at 0.
int m = 5;
int n = 4;
int[][] arr1 = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 16},
{17, 18, 19, 20}};
int[][] arr2 = new int[n][m];
int[][] arr3 = new int[n][m];
IntStream.range(0, m).forEach(i ->
IntStream.range(0, n).forEach(j -> {
// turn matrix 90º clockwise ⟳
arr2[j][m - 1 - i] = arr1[i][j];
// turn matrix 90º anticlockwise ⟲
arr3[n - 1 - j][i] = arr1[i][j];
}));
// Output to the markdown table:
String[] matrices = Stream.of(arr1, arr2, arr3)
.map(arr2d -> Arrays.stream(arr2d)
.map(arr -> Arrays.stream(arr)
.mapToObj(i -> String.format("%2d", i))
.toArray())
.map(Arrays::toString)
.collect(Collectors.joining("<br>")))
.toArray(String[]::new);
System.out.println("| original matrix | turn matrix 90º ⟳ | turn matrix 90º ⟲ |");
System.out.println("|---|---|---|");
System.out.println("|<pre>" + String.join("</pre>|<pre>", matrices) + "</pre>|");
original matrix | turn matrix 90º ⟳ | turn matrix 90º ⟲ |
---|---|---|
[ 1, 2, 3, 4] |
[17, 13, 9, 5, 1] |
[ 4, 8, 12, 16, 20] |
来源:https://stackoverflow.com/questions/56719451/how-do-i-rotate-a-matrix-90-degrees-counterclockwise-in-java