LongDz 的数字文墨提案

54. 螺旋矩阵

4 min

题目

54. 螺旋矩阵 中等

解法:边界收缩

思路

核心思想是通过边界收缩模拟螺旋路径。定义四个边界(上、下、左、右),按顺时针方向遍历边界元素后收缩对应边界,直到边界交错结束。

正确性在于:每次遍历完整条边界后,该边界即失效,收缩边界可确保内层元素形成新矩形。边界交错条件(top>bottom 或 left>right)能精确判断遍历完成,不会遗漏或重复访问元素。

  • Step 1: 初始化边界 top=0, bottom=m-1, left=0, right=n-1
  • Step 2: 从左到右遍历上边界,完成后 top++ 并检查边界
  • Step 3: 从上到下遍历右边界,完成后 right— 并检查边界
  • Step 4: 从右到左遍历下边界,完成后 bottom— 并检查边界
  • Step 5: 从下到上遍历左边界,完成后 left++ 并检查边界
  • Step 6: 循环执行 Step2-5 直到边界交错

复杂度

  • 时间复杂度: O(m×n)O(m \times n),每个元素被访问一次,m 和 n 分别为矩阵的行列数
  • 空间复杂度: O(1)O(1),仅使用常数额外空间存储边界变量(结果数组不计入)

代码

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        if (matrix.empty()) return ans;
        
        int top = 0, bottom = matrix.size() - 1;
        int left = 0, right = matrix[0].size() - 1;
        
        while (true) {
            // 1. 从左到右
            for (int i = left; i <= right; ++i) ans.push_back(matrix[top][i]);
            if (++top > bottom) break; // 上边界下移,如果越界则结束
            
            // 2. 从上到下
            for (int i = top; i <= bottom; ++i) ans.push_back(matrix[i][right]);
            if (--right < left) break; // 右边界左移
            
            // 3. 从右到左
            for (int i = right; i >= left; --i) ans.push_back(matrix[bottom][i]);
            if (--bottom < top) break; // 下边界上移
            
            // 4. 从下到上
            for (int i = bottom; i >= top; --i) ans.push_back(matrix[i][left]);
            if (++left > right) break; // 左边界右移
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        vector<int> ans;
        if (matrix.empty()) return ans;
        
        int top = 0, bottom = matrix.size() - 1;
        int left = 0, right = matrix[0].size() - 1;
        
        while (true) {
            // 1. 从左到右
            for (int i = left; i <= right; ++i) ans.push_back(matrix[top][i]);
            if (++top > bottom) break; // 上边界下移,如果越界则结束
            
            // 2. 从上到下
            for (int i = top; i <= bottom; ++i) ans.push_back(matrix[i][right]);
            if (--right < left) break; // 右边界左移
            
            // 3. 从右到左
            for (int i = right; i >= left; --i) ans.push_back(matrix[bottom][i]);
            if (--bottom < top) break; // 下边界上移
            
            // 4. 从下到上
            for (int i = bottom; i >= top; --i) ans.push_back(matrix[i][left]);
            if (++left > right) break; // 左边界右移
        }
        return ans;
    }
};