各位题友大家好! 今天是 @负雪明烛 坚持日更的第 50 天。今天力扣上的每日一题是「54. 螺旋矩阵」。

解题思路

题意是要我们螺旋向内遍历矩阵,力扣上类似地按照一定规则打印矩阵的题目有好几个。我觉得需要考虑以下几个问题:

  1. 起始位置
    2. 移动方向
    3. 边界
    4. 结束条件

今天这个题目只要把上面几个问题想清楚了,起始不难。

1. 起始位置

螺旋矩阵的遍历起点是矩阵的左上角,也就是 (0, 0) 位置。

2. 移动方向

起始位置的下一个移动方向是向右。在遍历的过程中,移动方向是固定的:

右 → ,下↓,左←,上↑

移动方向是按照上面的顺序循环进行的。只有当移动到了边界,才会更改方向。

3. 边界

本题的边界是最大的难点,因为是随着遍历的过程而变化的。螺旋遍历的时候,已经遍历的数字不能再次遍历,所以边界会越来越小。

我发现的规则是:如果当前行(列)遍历结束之后,就需要把这一行(列)的边界向内移动一格。

以下面的图为例, up, down, left, right 分别表示四个方向的边界。如果我们把第一行遍历结束(到了右边界),此时需要修改移动方向、并且把上边界 up 下移一行。

当绕了一圈后,从下向上走到 up 边界的时候,同样根据 up 判断边界。

由此可见,根据维护的四个方向的边界,就知道什么时候更改移动方向了。

4. 结束条件

螺旋遍历的结束条件是所有的位置都被遍历到。

代码

下面的代码不难:

  • up, down, left, right 分别表示四个方向的边界。
    - x, y 表示当前位置。

  • dirs 分别表示移动方向是 右、下、左、上

  • cur_d 表示当前的移动方向的下标,dirs[cur_d] 就是下一个方向需要怎么修改 x, y。

  • cur_d == 0 and y == right 表示当前的移动方向是向右,并且到达了右边界,此时将移动方向更改为向下,并且上边界 up 向下移动一格。

  • 结束条件是结果数组 res 的元素个数能与 matrix 中的元素个数。

    1. class Solution(object):
    2. def spiralOrder(self, matrix):
    3. """
    4. :type matrix: List[List[int]]
    5. :rtype: List[int]
    6. """
    7. if not matrix or not matrix[0]: return []
    8. M, N = len(matrix), len(matrix[0])
    9. left, right, up, down = 0, N - 1, 0, M - 1
    10. res = []
    11. x, y = 0, 0
    12. dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    13. cur_d = 0
    14. while len(res) != M * N:
    15. res.append(matrix[x][y])
    16. if cur_d == 0 and y == right:
    17. cur_d += 1
    18. up += 1
    19. elif cur_d == 1 and x == down:
    20. cur_d += 1
    21. right -= 1
    22. elif cur_d == 2 and y == left:
    23. cur_d += 1
    24. down -= 1
    25. elif cur_d == 3 and x == up:
    26. cur_d += 1
    27. left += 1
    28. cur_d %= 4
    29. x += dirs[cur_d][0]
    30. y += dirs[cur_d][1]
    31. return res
  • 时间复杂度:$O(M * N)$

  • 空间复杂度:$O(M * N)$,如果不把结果计算在内,那么空间复杂度为 $O(1)$

刷题心得

这种遍历的问题,本身其实不难,容易出错的地方在于移动方向、边界等处理。细节是魔鬼,刷题经验多了,对细节的处理也会更好一些。


OK,以上就是 @负雪明烛 写的今天题解的全部内容了,如果你觉得有帮助的话,求赞、求关注、求收藏。如果有疑问的话,请在下面评论,我会及时解答。

关注我,你将不会错过我的精彩动画题解、面试题分享、组队刷题活动,进入主页 @负雪明烛 右侧有刷题组织,从此刷题不再孤单。

祝大家牛年大吉!AC 多多,Offer 多多!我们明天再见!