题目描述
// 48. 旋转图像
// 给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
// 你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用
// 另一个矩阵来旋转图像。
题解
// 假设长度为len*len的矩阵。
// 旋转前
// 1 2 3 4
// 5 6 7 8
// 9 10 11 12
// 13 14 15 16
// 旋转后
// 13 9 5 1
// 14 10 6 2
// 15 11 7 3
// 16 12 8 4
// 外圈:
// 1 2 3 4
// 5 8
// 9 12
// 13 14 15 16
// 我们的思路是,先旋转外圈元素,再慢慢缩圈把内圈元素旋转过来,
// 而在圈中的旋转我们又采取分组的策略,一组一组元素地旋转过来。
// 所有组旋转过来,一圈元素就旋转好了,所有圈的元素旋转好了,
// 整个矩阵就旋转好了。
// 可以发现在外圈中:
// [0, 0], [0, len-1], [len-1, len-1], [len-1, 0] 为第一组
// [0, 1], [1, len-1], [len-1, len-2], [len-2, 0] 为第二组
// [0, 2], [2, len-1], [len-1, len-3], [len-3, 0] 为第三组
// i j j len-1-i len-1-i len-1-j len-1-j i
// 可以重写为:
// [i, j], [j, len-1-i], [len-1-i, len-1-j], [len-1-j, i] 为第一组
// [i, j], [j, len-1-i], [len-1-i, len-1-j], [len-1-j, i] 为第二组
// [i, j], [j, len-1-i], [len-1-i, len-1-j], [len-1-j, i] 为第三组
// 可以发现 i∈[0, (len-1)/2],j∈[0, jborder],每一个i就是一个圈,i移动一位,就缩一圈
// i的范围就是从外圈慢慢往内缩圈的过程。而j每移动一格,就是同一圈元素遍历一位,
// 所以j的范围就是遍历同圈元素的范围,其中jborder为j能够移动的右边界,实例中
// 我们以matrix[i][j]为例子,最外圈j能够移动到2(最右位置再往左一格),
// 所以jborder初始化为jborder=len-2=2。对i来说,案例中只有两圈,i只能够走到1,
// 所以jborder -= 1 = 1。可以看到每次缩圈,jborder
// 都会累减一次。所以循环之后将jborder累减1就行,很容易维护这个jborder边界。
//
// 取matrix的边长len,如果len为0直接返回,初始化j的边界jborder为len-2,
// 第一个for循环编写缩圈索引i的缩圈过程,
// 第二个for循环编写不同组之间的索引j的遍历过程,
// 因为是顺时针旋转,所以赋值的方向是逆时针的,
// 先把matrix[j][len-1-i](右上)存入temp,我们要把matrix[i][j](左上)
// 存入matrix[j][len-1-i](右上) 则有:matrix[j][len-1-i] = matrix[i][j],
// 这个时候matrix[i][j](左上)已经被使用过了,matrix[i][j]中的元素可以被替换了,
// 逆时针取上一个元素matrix[len-1-j][i](左下),将matrix[len-1-j][i](左下)
// 存入matrix[i][j](左上)。
// 这时候matrix[len-1-j][i](左下)已经使用过了,可以被替换,
// 我们再逆时针取上一个元素matrix[len-1-i][len-1-j](右下),
// 把它存入matrix[len-1-j][i](左下),这时候matrix[len-1-i][len-1-j](右下)
// 元素已经被使用了,我们将temp中的左上角元素存入matrix[len-1-i][len-1-j],
// 这一圈的第一组元素就完成了旋转。其他组其他圈同理。
// 执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
// 内存消耗:38.6 MB, 在所有 Java 提交中击败49.72%的用户
class Solution {
public void rotate(int[][] matrix) {
int len = matrix.length;
if (len == 0)
return;
int jborder = len - 2;
for (int i = 0; i <= (len - 1)/2; i++) {
for (int j = i; j <= jborder; j++) {
int temp = matrix[j][len-1-i];
matrix[j][len-1-i] = matrix[i][j];
matrix[i][j] = matrix[len-1-j][i];
matrix[len-1-j][i] = matrix[len-1-i][len-1-j];
matrix[len-1-i][len-1-j] = temp;
}
jborder -= 1;
}
}
}