题原文:
You are given an n x n 2D matrix representing an image.
Rotate the image by 90 degrees (clockwise).
Follow up:
Could you do this in-place?
题意理解: 在只允许使用常数内存空间的前提下,顺时针将nxn的矩阵转置90度。
一看题目,感觉比较简单,跟顺时针打印矩阵类似,其实还是有些不同的。此题比较有意思,做了两遍,大概有三种思路来解决这个问题。
第一个思路就是使用额外的O(n*n)的内存空间,找出转置前后矩阵中元素的对应关系,一一映射过去,然后再复制回来。这种思路可以达到题意中的转置要求,但是无法做到 in-place要求,也就是原地转置(我的理解是只允许使用常数空间),故这方法不可取。
第二种思路是先按水平中线翻转,再按左斜对角线翻转,两步一综合刚好完成顺时针旋转90度的要求,空间需要也是符合题意的,实现起来也比较直观。
第三种思路是转圈交换元素。这种思路需要较强的观察能力,抓住一个要点:先观察某一个元素在转置前后,一起了另外3个点的转移(先把改点临时存起来,它的位置会被A占用,A的位置又会被B占用,B的位置会被C占用,这时C的位置空出来了,也就是观察点在转置后的位置)。再把这种情况推广到其他点,不难发现,其他点的转置前后都有一个这个共同点。前两种思路比较直观,实现起来不容易搞混,第三种思路若不画图容易出现混淆。这里就第三种方法写两段代码,其实思路一样,效果一样,略有思维直观上的差异。
1 public class Solution { 2 public void rotate(int[][] matrix) { 3 if(null == matrix || matrix.length == 0) 4 return ; 5 6 int size = matrix.length; 7 8 for(int i=0; i<size/2; i++) 9 for(int j=i; j<size-1-i; j++){ 10 int tmp = matrix[j][i]; 11 matrix[j][i] = matrix[size-1-i][j]; 12 matrix[size -1 -i][j] = matrix[size -1 -j][size - 1 -i]; 13 matrix[size - 1 - j][size -1 -i] = matrix[i][size - 1 -j]; 14 matrix[i][size -1 -j] = tmp; 15 } 16 } 17 }
1 public class Solution { 2 public void rotate(int[][] matrix) { 3 if(null == matrix || matrix.length == 0) 4 return ; 5 6 int size = matrix.length; 7 8 for(int i=0; i<size/2; i++) 9 for(int j=i; j<size-1-i; j++){ 10 tmp = matrix[i][j]; 11 matrix[i][j] = matrix[size - 1 -j][i]; 12 matrix[size - 1 -j][i] = matrix[size -1 -i][size -1 -j]; 13 matrix[size -1 - i] [size -1 -j] = matrix[j][size -1-i]; 14 matrix[j][size -1 -i] = tmp; 15 } 16 } 17 }
短小精悍的代码总是让面试官欣喜不已,值得回味。第三种思路是交换次数较少的。