【Leetcode】48. 旋转图像

题目描述

在这里插入图片描述

// 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;
		}
    }
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锥栗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值