在问 · 算法题解

54. 螺旋矩阵

中等数组与矩阵按层收缩边界力扣原题 ↗

题目描述

输入一个 m 行 n 列的矩阵 matrix。

从左上角出发,沿顺时针方向一圈一圈向内绕:先向右走完第一行,再向下、向左、向上,依此类推,直到每个元素都被访问一次。

按访问的先后顺序,把所有元素放进一个数组返回。

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

解释:外圈依次是 1,2,3,6,9,8,7,4,最后剩中心的 5。

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

解释:外圈走完 1,2,3,4,8,12,11,10,9,5 后,内层剩下 6,7。

数据范围

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

解题思路:按层收缩边界

维护上下左右四条边,依次遍历上边、右边、下边、左边,每完成一条边就收缩边界,并在内层判断边界仍有效。

为什么正确

边界外的元素已按螺旋顺序输出,边界内仍未处理。

复杂度分析

时间 O(mn),空间 O(1)(不计输出)。

易错点

单行或单列剩余时要检查边界,避免重复遍历。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def spiralOrder(self, matrix):
        ans=[]; top,bottom=0,len(matrix)-1; left,right=0,len(matrix[0])-1
        while top<=bottom and left<=right:
            for j in range(left,right+1): ans.append(matrix[top][j])
            top+=1
            for i in range(top,bottom+1): ans.append(matrix[i][right])
            right-=1
            if top<=bottom:
                for j in range(right,left-1,-1): ans.append(matrix[bottom][j])
                bottom-=1
            if left<=right:
                for i in range(bottom,top-1,-1): ans.append(matrix[i][left])
                left+=1
        return ans

载入编辑器,自己跑一遍 →

其他解法

按层收缩边界只用常数空间,但要仔细处理单行、单列的情况;方向模拟更好写,需要额外标记空间。

解法 2:方向模拟 + 访问标记 时间 O(m·n),空间 O(m·n)

从左上角出发,按右、下、左、上的顺序循环使用方向。用同样大小的布尔矩阵记录已访问的格子。下一步越界或已访问时,顺时针转向。一共走 m·n 步。

不需要处理四条边界的细节,逻辑直观,不易出错。代价是额外的 O(m·n) 标记矩阵。

class Solution:
    def spiralOrder(self, matrix):
        m, n = len(matrix), len(matrix[0])
        seen = [[False] * n for _ in range(m)]
        dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
        ans = []
        i = j = d = 0
        for _ in range(m * n):
            ans.append(matrix[i][j])
            seen[i][j] = True
            ni, nj = i + dirs[d][0], j + dirs[d][1]
            if not (0 <= ni < m and 0 <= nj < n and not seen[ni][nj]):
                d = (d + 1) % 4
                ni, nj = i + dirs[d][0], j + dirs[d][1]
            i, j = ni, nj
        return ans

数组与矩阵 专题的其他题目

查看 数组与矩阵 全部题目 →