给定一个 n × n 的二维矩阵 matrix
表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
首先我们要知道旋转的数学本质
顺时针旋转90度的数学等效操作是:
- 转置矩阵(行列互换) + 水平翻转每一行
但更底层的实现是通过四个对称位置的元素轮换。
对于转置+水平翻转每一行 这个是有限制的 必须是方阵 但是对于这个题目是可以的 所以我会在下面写这个方法
转置就是第一行换成第一列 第二行换成第二列 然后再将每一行进行水平翻转 这个就是旋转九十度(可以在纸上画画)
对于四个对称位置的元素我们来分析一下
四个关键位置的关系
对于一个 n×n
矩阵中任意一点 (i,j)
,旋转时会影响以下四个对称位置:
- 左上角:
(i, j)
- 右上角:
(j, n-1-i)
- 右下角:
(n-1-i, n-1-j)
- 左下角:
(n-1-j, i)
- 每次顺时针旋转90度,坐标变化为:
(i,j) → (j,n-1-i) → (n-1-i,n-1-j) → (n-1-j,i) → (i,j)
你只要确定这四个位置是咋变的 那么其他也需要进行相同变换的元素 遵循的是一样的规律
那么我们再来看看 一共需要进行几轮呢?对于3*3的来说 只需要进行两轮(两个元素起头) 对于 4*4的来说 只需要进行4轮(4个元素起头) 那么就是2个元素和四个元素 那么行的话就是 n//2 列的话就是(n+1)//2
对于三的来说就是第一行的第一个元素和第二个元素 所以行是1个 列是两个 那么 0 和 0 1
对于四的来说 是第一行的第一个元素和第二个元素
第一行第一个 第一行的第二个 第二行的第一个 第二行的第二个 所以就是 n//2 (n+1)//2(肯定不能想着是第一行的第三个啊 肯定从最开始的行和最开始的列开始找初始的元素)
对于那四个角自己先推一遍 是适用于所有的
那么确定好起始的几个元素 再确定好交换的方式 就可以开始写代码了
class Solution(object): def rotate(self, matrix): n = len(matrix) for i in range(n//2): for j in range((n+1)//2): temp = matrix[i][j] matrix[i][j] = matrix[n - 1 - j][i] matrix[n - 1 - j][i] = matrix[n - 1 - i][n - 1 - j] matrix[n - 1 - i][n - 1 - j] = matrix[j][n - 1 - i] matrix[j][n - 1 - i] = temp matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ] solution=Solution() solution.rotate(matrix) print(matrix)
这个下面的为什么不是result= 然后打印result了呢?不return 了 反正矩阵旋转好了 都换好元素了 直接打印就行
注意题目要求是 必须原地旋转 所以这是原地修改这个矩阵 不要返回了 为什么不用return就修改了矩阵呢?这是因为Python的参数传递机制,列表是可变对象 函数内修改会直接反映到原对象 题目要求原地旋转 所以只需要修改matrix 无需返回
- 若函数中有
return matrix
,虽然能运行,但会误导他人认为需要接收返回值,且违背题目初衷。
好的 我们接下来试一下转置+水平翻转每一行的方式,这个代码还挺好写的
class Solution(object):
def rotate(self, matrix):
n = len(matrix)
for i in range(1,n):
for j in range(i):
temp = matrix[i][j]
matrix[i][j]=matrix[j][i]
matrix[j][i]=temp#到这里为止是已经转置好了
#然后需要按行开始进行翻转
for i in range(n):
matrix[i].reverse()
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
solution=Solution()
solution.rotate(matrix)
print(matrix)
#matrix[i]
是矩阵的第 i
行(一个列表)
#后面我要出一个关于矩阵的学习 一会儿就出 不拖拉了