题目大意
用二维数组(方阵)表示一幅图片,在O(1)空间复杂度的前提下完成图片顺时针旋转90度
解题思路
首先,如果只是单纯旋转图片90度,可以根据当前矩阵内容将其按一定规则复制到另一个矩阵当中,然后将复制完毕的矩阵覆盖回原矩阵,但这样显然无法做到in-place。那么只能利用矩阵的一些特点来实现就地旋转,显然就只能分析本地元素位置的关系。
将方阵看成一系列变长依次减少2的正方形,这样我们每次挪动每个正方形的边缘的那些数据就不会影响其他层的数据了,如下:
设矩形为n×n的方阵,然后针对每一个circle来寻找规律,从外到内,依次定义每一圈(circle)的序号为k(0,1...), 其实我们只要递归地移动每一圈第一行的数据,且每个数据只需要递归移动4次,也就是说,每个数据只需要刚好每条边走一次就行了。移动完第一行其他行也就移动完毕了,这样再定义第一行的元素序号为index(0,1,...,n-1),这样根据这两个参数,可以得出每一个元素其移动一次应该到达的位置,这样就可以很轻松地在O(1)空间复杂度下完成旋转。
元素位置变动规律公式如下:
(index+1+k)*n-1-k(起点)
-> (n-k)*n-1-k-index
-> (n-k-index-1)*n+k
-> k*(n+1)+index
-> (index+1+k)*n-1-k (回到起点位置)
这样一来,思路基本清楚,就可以非常轻松简单地写出代码。
总结
根据已知数据结构的特点来寻找合适的移动规律
代码
<span style="font-size:18px;">public class Solution {
void dfs(int n,int k, int deep, int index, int curLoc, int curNum, int[][] matrix){
if (deep == 4) return;
int nextLoc = 0;
switch(deep) {
case 0:nextLoc = (index+1+k)*n-1-k;break;
case 1:nextLoc = (n-k)*n-1-k-index;break;
case 2:nextLoc = (n-k-index-1)*n+k;break;
case 3:nextLoc = k*(n+1)+index;break;
}
int nextNum = matrix[nextLoc/n][nextLoc%n];
matrix[nextLoc/n][nextLoc%n] = curNum;
dfs(n,k,deep+1,index,nextLoc,nextNum,matrix);
}
public void rotate(int[][] matrix) {
int n = matrix[0].length;
for (int k = 0; k < n/2; k ++){
for (int index = 0; index < n-2*k-1; index ++){
int curLoc = k*(n+1)+index;
dfs(n,k,0,index,curLoc,matrix[curLoc/n][curLoc%n],matrix);
}
}
}
}</span>