二维数组 : 旋转矩阵

Posted 炫云云

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二维数组 : 旋转矩阵相关的知识,希望对你有一定的参考价值。

旋转矩阵

给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 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]
]

方法一:使用辅助数组

我们以题目中的示例二
[ 5 1 9 11 2 4 8 10 13 3 6 7 15 14 12 16 ] \\begin{bmatrix} 5 & 1 & 9 & 11 \\\\ 2 & 4 & 8 & 10 \\\\ 13 & 3 & 6 & 7 \\\\ 15 & 14 & 12 & 16 \\end{bmatrix} 52131514314986121110716

作为例子,分析将图像旋转 90 度之后,这些数字出现在什么位置。

对于矩阵中的第一行而言,在旋转后,它出现在倒数第一列的位置:

[ 5 1 9 11 ∘ ∘ ∘ ∘ ∘ ∘ ∘ ∘ ∘ ∘ ∘ ∘ ] ⇒ 旋 转 后 [ ∘ ∘ ∘ 5 ∘ ∘ ∘ 1 ∘ ∘ ∘ 9 ∘ ∘ ∘ 11 ] \\begin{bmatrix} 5 & 1 & 9 & 11 \\\\ \\circ & \\circ & \\circ & \\circ \\\\ \\circ & \\circ & \\circ & \\circ \\\\ \\circ & \\circ & \\circ & \\circ \\\\ \\end{bmatrix} \\Rightarrow{旋转后} \\begin{bmatrix} \\circ & \\circ & \\circ & 5 \\\\ \\circ & \\circ & \\circ & 1 \\\\ \\circ & \\circ & \\circ & 9 \\\\ \\circ & \\circ & \\circ & 11 \\end{bmatrix} 5191151911

并且,第一行的第 x x x 个元素在旋转后恰好是倒数第一列的第 x x x 个元素。

对于矩阵中的第二行而言,在旋转后,它出现在倒数第二列的位置:
[ ∘ ∘ ∘ ∘ 2 4 8 10 ∘ ∘ ∘ ∘ ∘ ∘ ∘ ∘ ] ⇒ 旋 转 后 [ ∘ ∘ 2 ∘ ∘ ∘ 4 ∘ ∘ ∘ 8 ∘ ∘ ∘ 10 ∘ ] \\begin{bmatrix} \\circ & \\circ & \\circ & \\circ \\\\ 2 & 4 & 8 & 10 \\\\ \\circ & \\circ & \\circ & \\circ \\\\ \\circ & \\circ & \\circ & \\circ \\end{bmatrix} \\Rightarrow {旋转后} \\begin{bmatrix} \\circ & \\circ & 2 & \\circ \\\\ \\circ & \\circ & 4 & \\circ \\\\ \\circ & \\circ & 8 & \\circ \\\\ \\circ & \\circ & 10 & \\circ \\end{bmatrix} 2481024810

对于矩阵中的第三行和第四行同理。这样我们可以得到规律:

对于矩阵中第 i i i 行的第 j j j 个元素,在旋转后,它出现在倒数第 i i i 列的第 j j j 个位置。

由于矩阵中的行列从 0 开始计数,因此对于矩阵中的元素 matrix [ row ] \\textit{matrix}[\\textit{row}] matrix[row],在旋转后,它的新位置为 matrix new [ c o l ] [ n − r o w − 1 ] \\textit{matrix}_\\textit{new} [col][n−row−1] matrixnew[col][nrow1]

这样以来,我们使用一个与 matrix \\textit{matrix} matrix大小相同的辅助数组 m a t r i x new {matrix}_\\textit{new} matrixnew,临时存储旋转后的结果。我们遍历 matrix \\textit{matrix} matrix中的每一个元素,根据上述规则将该元素存放到 m a t r i x new {matrix}_\\textit{new} matrixnew 中对应的位置。在遍历完成之后,再将 m a t r i x new {matrix}_\\textit{new} matrixnew 中的结果复制到原数组中即可。

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        # Python 这里不能 matrix_new = matrix 或 matrix_new = matrix[:] 因为是引用拷贝
        matrix_new = [[0] * n for _ in range(n)]
        for i in range(n):
            for j in range(n):
                matrix_new[j][n-i-1] = matrix[i][j]
        # 不能写成 matrix = matrix_new
        matrix[:] = matrix_new


复杂度分析

时间复杂度: O ( N 2 ) O(N^2) O(N2),其中 N N N matrix \\textit{matrix} matrix 的边长。

空间复杂度: O ( N 2 ) O(N^2) O(N2)。我们需要使用一个和 matrix \\textit{matrix} matrix 大小相同的辅助数组。

方法二:原地旋转

题目中要求我们尝试在不使用额外内存空间的情况下进行矩阵的旋转,也就是说,我们需要「原地旋转」这个矩阵。那么我们如何在方法一的基础上完成原地旋转呢?

来观察下正方形矩阵旋转 90 度时究竟发生了什么。

观察图中颜色相同的四个位置,当旋转 90 度后,对应位置的元素发生了顺时针的交换。

在这里插入图片描述

而相隔的两个位置是中心对称的,基于此可以计算出发生交换的四个元素 位置关系。

设四个位置中,位于 左上角区域 的位置坐标为 ( i , j ) (i,j) (i,j),则按顺时针顺序,四个位置分别为 ( i , j ) , ( j , n − i − 1 ) , ( n − i − 1 , n − j − 1 ) , ( n − j − 1 , i ) (i,j), (j, n-i-1), (n-i-1,n-j-1), (n-j-1,i) (i,j),(j,ni1),(ni1,nj二维数组 : 旋转矩阵

二维数组6:数组的水平翻转

数组问题之《下一个排列》《旋转图像》以及二分查找之《搜索二维矩阵》

数组问题之《下一个排列》《旋转图像》以及二分查找之《搜索二维矩阵》

计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和

将多个二维数组存储在一个变量中[关闭]