数组和矩阵问题:将正方形矩阵顺时针转动90度
【题目】
给定一个 N*N 的矩阵 matrix, 把这个矩阵调整成顺时针转动90度后形式。
例如:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
顺时针转动90度后为:
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
【要求】
额外空间复杂度为 O(1)
【难度】
一星
【解答】
这里仍然使用分圈处理的方式,在矩阵中用左上角的坐标(tR, tC)和右下角的坐标(dR, dC) 就可以表示一个子矩阵。比如,题目中的矩阵,当(tR, tC)=(0,0), (dR,dC)=(3,3) 时,表示的子矩阵就是整个矩阵,那么这个子矩阵最外层的部分如下:
1 2 3 4
5 8
9 12
13 14 15 16
在这个外圈中, 1,4,16,13 为一组,然后让1占据4的位置,4占据16的位置,16占据13的位置,13占据1的位置,一组就调整完了。然后,2,8,15,9 为一组,继续占据调整的过程,最后 3,12,14,5 为一组,继续占据调整的过程。然后(tR, tC)=(0,0)、(dR,dC)=(3,3) 的子矩阵外层就调整完毕了。接下来令tR和tC加1,dR和dC减1,即(tR,tC)=(1,1), (dR, dC)=(2,2), 此时表示的子矩阵如下:
6 7
10 11
这个外层只有一组,就是6,7,11,10,占据调整之后即可。所以,如果子矩阵的大小是M*M,一共就有 M-1 组, 分别进行占据调整即可。
具体过程请参看如下代码的 rotate 方法。
1 public class Main { 2 3 public static void main(String[] args) { 4 int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; 5 System.out.println("原矩阵:"); 6 for(int i = 0; i < matrix.length; i++){ 7 for(int j = 0; j < matrix[i].length; j++){ 8 System.out.print(matrix[i][j] + " "); 9 } 10 System.out.println(); 11 } 12 13 new Main().rotate(matrix); 14 System.out.println("\n顺时针旋转90度后:"); 15 for(int i = 0; i < matrix.length; i++){ 16 for(int j = 0; j < matrix[i].length; j++){ 17 System.out.print(matrix[i][j] + " "); 18 } 19 System.out.println(); 20 } 21 } 22 23 //顺时针旋转90度 24 public void rotate(int[][] matrix){ 25 int tR = 0; 26 int tC = 0; 27 int dR = matrix.length - 1; 28 int dC = matrix[0].length - 1; 29 while(tR <= dR && tC <= dC){ 30 rotateEdge(matrix, tR++, tC++, dR--, dC--); 31 } 32 } 33 34 //旋转子矩阵外层 35 public void rotateEdge(int[][] m, int tR, int tC, int dR, int dC){ 36 //确定旋转次数 37 int times = dR - tR; 38 for(int i = 0; i < times; i++){ 39 //要交换的四个位置按顺时针方向分别为:m[tR][tC+i]、m[tR+i][dC]、m[dR][dC-i]、m[dR-i][tC] 40 int tmp = m[tR][tC+i]; 41 m[tR][tC+i] = m[dR-i][tC]; 42 m[dR-i][tC] = m[dR][dC-i]; 43 m[dR][dC-i] = m[tR+i][dC]; 44 m[tR+i][dC] = tmp; 45 } 46 } 47 48 }