LeetCode 54: Spiral Matrix (Boundary Shrink Traversal)
LeetCode 54MatrixSimulationToday we solve LeetCode 54 - Spiral Matrix.
Source: https://leetcode.com/problems/spiral-matrix/
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 ansvar 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 矩阵,按螺旋顺序返回所有元素:先走上边一行,再走右边一列,再走下边一行,再走左边一列,逐层向内收缩。
核心思路
用四个边界 top、bottom、left、right 控制当前“环”。每走完一条边就收缩对应边界。关键是收缩后要判断边界是否交错,避免单行/单列时重复读取。
算法步骤
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 ansvar 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