LeetCode 热题 HOT 100 第二十一天 48. 旋转图像 中等题 用python3求解

题目地址

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例 1:
在这里插入图片描述

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

示例 2:
在这里插入图片描述

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

提示:
n == matrix.length == matrix[i].length
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000

在这里插入图片描述
题目要求不借助辅助矩阵,通过在原矩阵中直接原地修改,实现**空间复杂度 O(1)**的解法。

以位于矩阵四个角点的元素为例,设矩阵左上角元素 A 、右上角元素 B 、右下角元素 C 、左下角元素 D 。矩阵旋转 90º 后,相当于依次先后执行D→A , C→D , B→C ,A→B 修改元素,即如下「首尾相接」的元素旋转操作:

A←D←C←B←A

在这里插入图片描述

如上图所示,由于第 1 步D→A 已经将 A 覆盖(导致 A 丢失),此丢失导致最后第 4步 A→B 无法赋值。为解决此问题,考虑借助一个辅助变量 tmp预先存储 A ,此时的旋转操作变为:

暂存 tmp=A
A←D←C←B←tmp

一轮可以完成矩阵 4 个元素的旋转。因而,只要分别以矩阵左上角 1/4的各元素为起始点执行以上旋转操作,即可完整实现矩阵旋转。

具体来看,当矩阵大小n为偶数时,取前n/2行、前n/2列的元素为起始点;当矩阵大小n为奇数时,取前n/2行、前(n+1)/2列的元素为起始点。

以示例二为例,图片具体流程如下:参考地址
分别以矩阵左上角的那4个元素为起点,总共进行4轮旋转
在这里插入图片描述
第一轮旋转:以元素5(坐标为matrix[0][0])为起点进行旋转,元素5暂存于tmp。
在这里插入图片描述
在这里插入图片描述
第二轮旋转:以元素1(坐标为matrix[0][1])为起点进行旋转,元素1暂存于tmp。
在这里插入图片描述
在这里插入图片描述
第三轮旋转:以元素2(坐标为matrix[1][0])为起点进行旋转,元素2暂存于tmp。
在这里插入图片描述
在这里插入图片描述
第四轮旋转:以元素4(坐标为matrix[1][1])为起点进行旋转,元素4暂存于tmp。
在这里插入图片描述
在这里插入图片描述
至此,矩阵顺时针旋转90°完成。

代码实现:

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        # 设矩阵行列数为 n
        n = len(matrix)
        # 起始点范围为 0 <= i < n // 2 , 0 <= j < (n + 1) // 2
        # 其中 '//' 为整数除法
        for i in range(n // 2):
            for j in range((n + 1) // 2):
                print('i',i)
                print('j',j)
                # 暂存 A 至 tmp
                tmp = matrix[i][j]
                # 元素旋转操作 A <- D <- C <- B <- tmp
                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] = tmp

注:
示例一为三阶矩阵,那么n=3,for i in range(n // 2)和for j in range((n + 1) // 2),分别表示i只取0,j取0和1。
示例二为四阶矩阵,那么n=4,for i in range(n // 2)和for j in range((n + 1) // 2),分别表示i取0和1,j取0和1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值