LC 旋转矩阵

给你一幅由 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]
]

Solution:

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        
        """
        size = len(matrix[0])
        times = size
        for i in range(times):
            if times >= 2:
                for j in range(i, times - 1):
                    tmp = matrix[i][j]
                    matrix[i][j] = matrix[size - j - 1][i]
                    matrix[size - j - 1][i] = matrix[size - i - 1][size - j - 1]
                    matrix[size - i - 1][size - j - 1] = matrix[j][size - i - 1]
                    matrix[j][size - i - 1] = tmp
                times = times - 1
            else:
                break

解题思路:
这个题初拿到手,纠结了什么叫不用额外的内存空间,其实就是原地算法。一个原地算法(in-place algorithm)是一种使用小的,固定数量的额外之空间来转换资料的算法。当算法执行时,输入的资料通常会被要输出的部分覆盖掉。简而言之,我理解的原地就是覆盖原数据,而且你只能借助固定数量的额外空间,比如一个temp,而不是将数组放到一个新的变量里。下面是我先想到的用tmp辅助更新数据的思路。

  1. 找规律,旋转九十度,那么其实我们可以发现,经过matrix[i][j]经过旋转,这个数字在第几行就变到了倒数第几列,在第几列就变到了第几行,也就是matrix[i][j] -> matrix[j][size - i - 1],拿几个具体的例子看看,这里我在图里举例了四个角的变换,不难发现这个规律

    image.png

  2. 考虑怎么换呢,俩俩置换是不可能的,因为我们已经找到规律了,如果俩俩置换,那原来的数字会被替换掉,规律就不成立了,于是我们可以选择四个四个的变,因为每四个变换都会是一个环,规律还是成立。(最后介绍了不会被替换的简便方法)


    image.png
  3. 下面考虑该怎么换呢,只用一个tmp我们可以一次将四个数字变换到位,意思跟冒泡排序差不多,但是这回得倒着推,先把1给tmp,再把7给1,9给7,3给9,最后把tmp给3。如上图蓝色的圆圈编号的顺序操作,顺序无所谓,懂怎么个流程就行了。这种旋转屡试不爽


    image.png
  4. 下面我们找需要旋转多少次,怎么样才结束呢,看上图,
    当size为3的时候,我只需要做一次外层的旋转,且这个外层旋转做了两次(0,0)和(0,1)所在的两个环。
    当size==4 的时候做了2层旋转,最外面的那一层做了(0,0),(0,1)(0,2)环旋转,内层做了(1,1)环旋转
    当size==5的时候,做了3层旋转,最外面一层做了(0,0)(0,1)(0,2)(0,3),内一层(1,1)(1,2)
    可以发现,每往内一层,需要旋转的正方形的边长 - 2,直到最里面那层的正方形小于2,也就是只剩1个或者没有了就停止了旋转了。

Note:
本来以为不用temp值会被替换掉,后来尝试了一下发现,python可以同时对多个值操的置换的时候不会被覆盖,所以把代码更新了一下

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        
        """
        size = len(matrix[0])
        times = size
        for i in range(times):
            if times >= 2:
                for j in range(i, times - 1):
                    matrix[i][j], matrix[size - j - 1][i], matrix[size - i - 1][size - j - 1], matrix[j][size - i - 1] = \
                matrix[size - j - 1][i], matrix[size - i - 1][size - j - 1], matrix[j][size - i - 1], matrix[i][j]
                    # tmp = matrix[i][j]                    
                    # matrix[size - j - 1][i] = matrix[size - i - 1][size - j - 1]
                    # matrix[size - i - 1][size - j - 1] = matrix[j][size - i - 1]
                    # matrix[j][size - i - 1] = tmp
                times = times - 1
            else:
                break

你可能感兴趣的:(LC 旋转矩阵)