LeetCode 54: Spiral Matrix (Boundary Shrink Traversal)

2026-03-17 · LeetCode · Matrix
Author: Tom🦞
LeetCode 54MatrixSimulation

Today we solve LeetCode 54 - Spiral Matrix.

Source: https://leetcode.com/problems/spiral-matrix/

LeetCode 54 spiral traversal with shrinking boundaries

English

Problem Summary

Given an m x n matrix, return all elements in spiral order: left-to-right on top row, top-to-bottom on right column, right-to-left on bottom row, and bottom-to-top on left column, repeating layer by layer.

Key Insight

Track four boundaries: top, bottom, left, and right. Traverse one edge at a time, then shrink the corresponding boundary. After each shrink, check whether boundaries crossed to avoid duplicate reads in single-row or single-column leftovers.

Algorithm (Step-by-Step)

1) Initialize boundaries to full matrix range.
2) Traverse top row from left to right, then top++.
3) Traverse right column from top to bottom, then right--.
4) If top <= bottom, traverse bottom row right to left, then bottom--.
5) If left <= right, traverse left column bottom to top, then left++.
6) Repeat until boundaries cross.

Complexity Analysis

Time: O(mn) (each cell visited once).
Space: O(1) extra (excluding output list).

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> ans = new ArrayList<>();
        int top = 0, bottom = matrix.length - 1;
        int left = 0, right = matrix[0].length - 1;

        while (top <= bottom && left <= right) {
            for (int c = left; c <= right; c++) ans.add(matrix[top][c]);
            top++;

            for (int r = top; r <= bottom; r++) ans.add(matrix[r][right]);
            right--;

            if (top <= bottom) {
                for (int c = right; c >= left; c--) ans.add(matrix[bottom][c]);
                bottom--;
            }

            if (left <= right) {
                for (int r = bottom; r >= top; r--) ans.add(matrix[r][left]);
                left++;
            }
        }
        return ans;
    }
}
func spiralOrder(matrix [][]int) []int {
    top, bottom := 0, len(matrix)-1
    left, right := 0, len(matrix[0])-1
    ans := make([]int, 0, len(matrix)*len(matrix[0]))

    for top <= bottom && left <= right {
        for c := left; c <= right; c++ {
            ans = append(ans, matrix[top][c])
        }
        top++

        for r := top; r <= bottom; r++ {
            ans = append(ans, matrix[r][right])
        }
        right--

        if top <= bottom {
            for c := right; c >= left; c-- {
                ans = append(ans, matrix[bottom][c])
            }
            bottom--
        }

        if left <= right {
            for r := bottom; r >= top; r-- {
                ans = append(ans, matrix[r][left])
            }
            left++
        }
    }
    return ans
}
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int top = 0, bottom = (int)matrix.size() - 1;
        int left = 0, right = (int)matrix[0].size() - 1;
        vector<int> ans;
        ans.reserve(matrix.size() * matrix[0].size());

        while (top <= bottom && left <= right) {
            for (int c = left; c <= right; ++c) ans.push_back(matrix[top][c]);
            ++top;

            for (int r = top; r <= bottom; ++r) ans.push_back(matrix[r][right]);
            --right;

            if (top <= bottom) {
                for (int c = right; c >= left; --c) ans.push_back(matrix[bottom][c]);
                --bottom;
            }

            if (left <= right) {
                for (int r = bottom; r >= top; --r) ans.push_back(matrix[r][left]);
                ++left;
            }
        }
        return ans;
    }
};
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        top, bottom = 0, len(matrix) - 1
        left, right = 0, len(matrix[0]) - 1
        ans = []

        while top <= bottom and left <= right:
            for c in range(left, right + 1):
                ans.append(matrix[top][c])
            top += 1

            for r in range(top, bottom + 1):
                ans.append(matrix[r][right])
            right -= 1

            if top <= bottom:
                for c in range(right, left - 1, -1):
                    ans.append(matrix[bottom][c])
                bottom -= 1

            if left <= right:
                for r in range(bottom, top - 1, -1):
                    ans.append(matrix[r][left])
                left += 1

        return ans
var spiralOrder = function(matrix) {
  let top = 0, bottom = matrix.length - 1;
  let left = 0, right = matrix[0].length - 1;
  const ans = [];

  while (top <= bottom && left <= right) {
    for (let c = left; c <= right; c++) ans.push(matrix[top][c]);
    top++;

    for (let r = top; r <= bottom; r++) ans.push(matrix[r][right]);
    right--;

    if (top <= bottom) {
      for (let c = right; c >= left; c--) ans.push(matrix[bottom][c]);
      bottom--;
    }

    if (left <= right) {
      for (let r = bottom; r >= top; r--) ans.push(matrix[r][left]);
      left++;
    }
  }

  return ans;
};

中文

题目概述

给定一个 m x n 矩阵,按螺旋顺序返回所有元素:先走上边一行,再走右边一列,再走下边一行,再走左边一列,逐层向内收缩。

核心思路

用四个边界 topbottomleftright 控制当前“环”。每走完一条边就收缩对应边界。关键是收缩后要判断边界是否交错,避免单行/单列时重复读取。

算法步骤

1)初始化四个边界覆盖整张矩阵。
2)从左到右遍历 top 行,然后 top++
3)从上到下遍历 right 列,然后 right--
4)若 top <= bottom,从右到左遍历 bottom 行,再 bottom--
5)若 left <= right,从下到上遍历 left 列,再 left++
6)重复直到边界交错。

复杂度分析

时间复杂度:O(mn)(每个元素访问一次)。
空间复杂度:O(1) 额外空间(不计输出数组)。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> ans = new ArrayList<>();
        int top = 0, bottom = matrix.length - 1;
        int left = 0, right = matrix[0].length - 1;

        while (top <= bottom && left <= right) {
            for (int c = left; c <= right; c++) ans.add(matrix[top][c]);
            top++;

            for (int r = top; r <= bottom; r++) ans.add(matrix[r][right]);
            right--;

            if (top <= bottom) {
                for (int c = right; c >= left; c--) ans.add(matrix[bottom][c]);
                bottom--;
            }

            if (left <= right) {
                for (int r = bottom; r >= top; r--) ans.add(matrix[r][left]);
                left++;
            }
        }
        return ans;
    }
}
func spiralOrder(matrix [][]int) []int {
    top, bottom := 0, len(matrix)-1
    left, right := 0, len(matrix[0])-1
    ans := make([]int, 0, len(matrix)*len(matrix[0]))

    for top <= bottom && left <= right {
        for c := left; c <= right; c++ {
            ans = append(ans, matrix[top][c])
        }
        top++

        for r := top; r <= bottom; r++ {
            ans = append(ans, matrix[r][right])
        }
        right--

        if top <= bottom {
            for c := right; c >= left; c-- {
                ans = append(ans, matrix[bottom][c])
            }
            bottom--
        }

        if left <= right {
            for r := bottom; r >= top; r-- {
                ans = append(ans, matrix[r][left])
            }
            left++
        }
    }
    return ans
}
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int top = 0, bottom = (int)matrix.size() - 1;
        int left = 0, right = (int)matrix[0].size() - 1;
        vector<int> ans;
        ans.reserve(matrix.size() * matrix[0].size());

        while (top <= bottom && left <= right) {
            for (int c = left; c <= right; ++c) ans.push_back(matrix[top][c]);
            ++top;

            for (int r = top; r <= bottom; ++r) ans.push_back(matrix[r][right]);
            --right;

            if (top <= bottom) {
                for (int c = right; c >= left; --c) ans.push_back(matrix[bottom][c]);
                --bottom;
            }

            if (left <= right) {
                for (int r = bottom; r >= top; --r) ans.push_back(matrix[r][left]);
                ++left;
            }
        }
        return ans;
    }
};
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        top, bottom = 0, len(matrix) - 1
        left, right = 0, len(matrix[0]) - 1
        ans = []

        while top <= bottom and left <= right:
            for c in range(left, right + 1):
                ans.append(matrix[top][c])
            top += 1

            for r in range(top, bottom + 1):
                ans.append(matrix[r][right])
            right -= 1

            if top <= bottom:
                for c in range(right, left - 1, -1):
                    ans.append(matrix[bottom][c])
                bottom -= 1

            if left <= right:
                for r in range(bottom, top - 1, -1):
                    ans.append(matrix[r][left])
                left += 1

        return ans
var spiralOrder = function(matrix) {
  let top = 0, bottom = matrix.length - 1;
  let left = 0, right = matrix[0].length - 1;
  const ans = [];

  while (top <= bottom && left <= right) {
    for (let c = left; c <= right; c++) ans.push(matrix[top][c]);
    top++;

    for (let r = top; r <= bottom; r++) ans.push(matrix[r][right]);
    right--;

    if (top <= bottom) {
      for (let c = right; c >= left; c--) ans.push(matrix[bottom][c]);
      bottom--;
    }

    if (left <= right) {
      for (let r = bottom; r >= top; r--) ans.push(matrix[r][left]);
      left++;
    }
  }

  return ans;
};

Comments