LeetCode 48. 旋转图像(中)
将给定的矩阵分成四个矩形 并且将原问题划归为旋转这些矩形的问题。
题目
给定一个 n × n 的二维矩阵表示一个图像。 将图像顺时针旋转 90 度。
说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例
示例 1: 1
2
3
4
5
6
7
8
9
10
11
12给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]1
2
3
4
5
6
7
8
9
10
11
12
13
14给定 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]
]
考察知识点
数组
核心思想
方法一、转置加翻转
最直接的想法是先转置矩阵,然后翻转每一行。这个简单的方法已经能达到最优的时间复杂度\(O(N^2)\)。
算法
- 根据输入数据,得到
n
的大小。 - 先获得转置矩阵
- 列号从
0
一直到n-1
,外循环是列i
代表列。- 行号从
i
一直到n-1
内循环是行j
代表行。
- 行号从
- 然后reserve每一行
方法二、旋转四个矩形
将给定的矩阵分成四个矩形并且将原问题划归为旋转这些矩形的问题。
解法很直接 - 可以在第一个矩形中移动元素并且在 长度为 4
个元素的临时列表中移动它们。
![]() |
![]() |
---|---|
![]() |
![]() |
算法
获取n的大小
开始外层遍历,范围是 0 - (n-2),如果n=3,则遍历0、1两次。每次调整一组4个数字。
for i in range(n // 2 + n % 2)
,外层的i
行号。开始内存遍历,
for j in range(n // 2):
。- 先声明
tmp = [0] * 4
、row = i
、col = j
。 for k in range(4)
循环四次,获取四个矩形块里的值 保存在tmp
中。注意行号和列号的切换方式row, col = col, n - 1 - row
。for k in range(4)
循环四次,利用保存在tmp
中的结果,旋转四个矩阵块,其填充顺序是tmp[3]
、tmp[0]
、tmp[1]
、tmp[2]
,填充方式matrix[row][col] = tmp[(k - 1) % 4]
。行列切换方式和上一步保持一致。
1
2k 0 1 2 3
(k - 1) % 4 3 0 1 2简而言之,将整个 \(n \times n\) 的矩阵,分成了4个块,每个位置的数字,必然属于其中一个块,然后一次替换一组(4个数字),如果一个块由 \(m\) 个数字组成,就会替换 \(m\) 次,最终就完成了整个矩阵的旋转。
- 先声明
Python版本
方法一的实现
1 |
|
执行用时 :56 ms, 在所有 Python3 提交中击败了16.61%的用户
内存消耗 :13.3 MB, 在所有 Python3 提交中击败了26.99%的用户
时间复杂度:\(O(N^2)\)。
空间复杂度:\(O(1)\) 由于旋转操作是 就地 完成的。
方法二的实现
1 |
|
执行用时 :40 ms, 在所有 Python3 提交中击败了59.48%的用户
内存消耗 :13.5 MB, 在所有 Python3 提交中击败了26.99%的用户
时间复杂度:\(O(N^2)\) 是两重循环的复杂度。
空间复杂度:\(O(1)\) 由于我们在一次循环中的操作是 就地 完成的,并且我们只用了长度为 4 的临时列表做辅助。
在单次循环中旋转 4 个矩形
1 |
|
执行用时 :36 ms, 在所有 Python3 提交中击败了80.25%的用户。 内存消耗 :13.3 MB, 在所有 Python3 提交中击败了26.99%的用户。 时间复杂度:\(O(N^2)\) 是两重循环的复杂度。 空间复杂度:\(O(1)\) 由于旋转操作是 就地 完成的。
有效语法糖
1、Python3 快速交换两变量的值 利用此格式 a, b = b, a
,可以随意交换变量值。
1 |
|
2、负数除法的取值
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!