Leetcode 054 螺旋矩阵 python

每天更新一道python leetcode题,力求讲解清晰准确,客官们可以点赞或者关注。

给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素。

示例 1:

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

示例 2:

输入:
[
  [1, 2, 3, 4],
  [5, 6, 7, 8],
  [9,10,11,12]
]
输出: [1,2,3,4,8,12,11,10,9,5,6,7]

思路:设置四种case,观察到第一种case是行不变列一直在变,第二种case的列数不变行数变,以此类推。

并且可以发现规律,第一次遍历的个数等于列数,第二次遍历的个数等于行数减一,第三次等于列数减一,第四次等于行数再减一。。。

算法过程:

解释代码中的参数作用

case表明是哪一种情况,0对应向右, 1对应向下,2 对应向左,3对应向上

ri, ci 表示我们当前遍历的点的位置坐标。

row, col, 用来代表这一次运动的步数。我们用它们可以组合出下一次终点的坐标。举例,若是case0向右运动,所以(ri, ci + col)就是运动末位置的后一项。注意到每次运动的步数都逐步减少,发现规律:当你移完横向运动类型的运动后,row -= 1;而竖的运动(case 1 3), col -= 1。然后每一次case结尾更新ri, ci也即此次运动的末尾坐标和下一次开始的起始坐标。

class Solution:
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        def cyc(row, column, ri, ci, case):
            #递归终止条件
            if row == 0 or column == 0:
                return
            #第一种case,横着走
            if case == 0:
                #结束的位置的column
                endci = ci + column
                for i in range(ci, endci):
                    #添加元素
                    re.append(matrix[ri][i])
                #横移后row的长度减一
                row -= 1
                ri += 1
                ci = endci-1
                #我们想让case 不断增加但在0-4内循环
                case = (case + 1)%4
                cyc(row, column, ri, ci, case)

            elif case == 1:
                endri = ri + row
                for i in range(ri, endri):
                    re.append(matrix[i][ci])
                column -= 1
                ci -= 1
                ri = endri-1
                case = (case+1)%4
                cyc(row, column, ri, ci, case)

            elif case == 2:
                endci = ci - column
                for i in range(ci, endci, -1):
                    re.append(matrix[ri][i])
                row -= 1
                ri = ri - 1
                ci = endci + 1
                case = (case+1)%4
                cyc(row, column, ri, ci, case)

            elif case == 3:
                endri = ri - row
                for i in range(ri, endri, -1):
                    re.append(matrix[i][ci])
                column -= 1
                ri = endri + 1
                ci = ci + 1
                case = (case+1)%4
                cyc(row, column, ri, ci, case)

        re = []
        row = len(matrix)
        if row == 0:
            return []
        column = len(matrix[0])
        cyc(row, column, 0, 0, 0)
        return re

算法证明:

这里面最难思考的就是row -= 1和 col -= 1,但这一点是可以自己验证的。

这里无法提供数学上的证明,只能归纳思考。

总结难点:

1)建模,抽象出四种运动,发现这四种运动的不同

2)为函数设置参数,记录每次要走的步数和起始的位置。

3)发现row, col即每次要走的步数与上一次走的方向的数学关系。

猜你喜欢

转载自blog.csdn.net/weixin_41958153/article/details/81141614
今日推荐