Spiral Matrix
Peel layers in four-direction order, shrinking the active rectangle after each side.
4 min read
matrix simulation
Problem#
Given an m x n matrix, return all elements in spiral order starting from the top-left, walking right → down → left → up, then inward.
Examples#
[[1,2,3],[4,5,6],[7,8,9]]→[1,2,3,6,9,8,7,4,5][[1,2,3,4],[5,6,7,8],[9,10,11,12]]→[1,2,3,4,8,12,11,10,9,5,6,7]
Constraints#
m == matrix.length,n == matrix[i].length,1 <= m, n <= 10.
Approach#
Maintain four bounds: top, bottom, left, right. Repeatedly walk the top row left-to-right, right column top-to-bottom, bottom row right-to-left, and left column bottom-to-top. After each side, shrink the corresponding bound and check if the rectangle is still non-degenerate.
Solution#
class Solution {public: vector<int> spiralOrder(vector<vector<int>>& matrix) { int m = matrix.size(), n = matrix[0].size(); int top = 0, bottom = m - 1, left = 0, right = n - 1; vector<int> ans; ans.reserve(m * n); while (top <= bottom && left <= right) { for (int j = left; j <= right; ++j) ans.push_back(matrix[top][j]); ++top; for (int i = top; i <= bottom; ++i) ans.push_back(matrix[i][right]); --right; if (top <= bottom) { for (int j = right; j >= left; --j) ans.push_back(matrix[bottom][j]); --bottom; } if (left <= right) { for (int i = bottom; i >= top; --i) ans.push_back(matrix[i][left]); ++left; } } return ans; }};func spiralOrder(matrix [][]int) []int { m, n := len(matrix), len(matrix[0]) top, bottom, left, right := 0, m-1, 0, n-1 ans := make([]int, 0, m*n) for top <= bottom && left <= right { for j := left; j <= right; j++ { ans = append(ans, matrix[top][j]) } top++ for i := top; i <= bottom; i++ { ans = append(ans, matrix[i][right]) } right-- if top <= bottom { for j := right; j >= left; j-- { ans = append(ans, matrix[bottom][j]) } bottom-- } if left <= right { for i := bottom; i >= top; i-- { ans = append(ans, matrix[i][left]) } left++ } } return ans}from typing import List
class Solution: def spiralOrder(self, matrix: List[List[int]]) -> List[int]: m, n = len(matrix), len(matrix[0]) top, bottom, left, right = 0, m - 1, 0, n - 1 ans: List[int] = [] 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 ansfunction spiralOrder(matrix) { const m = matrix.length, n = matrix[0].length; let top = 0, bottom = m - 1, left = 0, right = n - 1; const ans = []; while (top <= bottom && left <= right) { for (let j = left; j <= right; j++) ans.push(matrix[top][j]); top++; for (let i = top; i <= bottom; i++) ans.push(matrix[i][right]); right--; if (top <= bottom) { for (let j = right; j >= left; j--) ans.push(matrix[bottom][j]); bottom--; } if (left <= right) { for (let i = bottom; i >= top; i--) ans.push(matrix[i][left]); left++; } } return ans;}class Solution { public List<Integer> spiralOrder(int[][] matrix) { int m = matrix.length, n = matrix[0].length; int top = 0, bottom = m - 1, left = 0, right = n - 1; List<Integer> ans = new ArrayList<>(m * n); while (top <= bottom && left <= right) { for (int j = left; j <= right; j++) ans.add(matrix[top][j]); top++; for (int i = top; i <= bottom; i++) ans.add(matrix[i][right]); right--; if (top <= bottom) { for (int j = right; j >= left; j--) ans.add(matrix[bottom][j]); bottom--; } if (left <= right) { for (int i = bottom; i >= top; i--) ans.add(matrix[i][left]); left++; } } return ans; }}function spiralOrder(matrix: number[][]): number[] { const m = matrix.length, n = matrix[0].length; let top = 0, bottom = m - 1, left = 0, right = n - 1; const ans: number[] = []; while (top <= bottom && left <= right) { for (let j = left; j <= right; j++) ans.push(matrix[top][j]); top++; for (let i = top; i <= bottom; i++) ans.push(matrix[i][right]); right--; if (top <= bottom) { for (let j = right; j >= left; j--) ans.push(matrix[bottom][j]); bottom--; } if (left <= right) { for (let i = bottom; i >= top; i--) ans.push(matrix[i][left]); left++; } } return ans;}Editorial#
The two extra if guards after the bottom and left passes are vital when the matrix is non-square — once you’ve consumed one row or column, the next direction may overlap and double-add elements without the check.
Complexity#
- Time: O(m*n).
- Space: O(1) extra.
Concept revision#
Related#