137.Spiral Matrix
Problem
Given an m x n matrix, return all of its elements in spiral order: start at the top-left, go right along the top row, down the right column, left along the bottom row, up the left column, and keep spiralling inward until every element has been visited.
Examples
Input: matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]Input: matrix = [[1,2,3,4],
[5,6,7,8],
[9,10,11,12]]
Output: [1,2,3,4,8,12,11,10,9,5,6,7]Constraints
m == matrix.length,n == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
๐ก Key Insight
The spiral is a sequence of shrinking rectangle boundaries. Keep four walls โ top, bottom, left, right โ and after walking each side, move that wall inward by one. The only subtlety is non-square matrices: after the top row and right column, the remaining rectangle may already be empty, so check top <= bottom and left <= right before walking the bottom row and left column.
Simulation with Visited Array
TimeO(m ยท n)SpaceO(m ยท n)Intuition
Simulate a walker. It moves in direction order right โ down โ left โ up. When the next cell is outside the matrix or already visited, it turns clockwise. After m ยท n steps every cell has been collected.
Algorithm
dr = {0, 1, 0, -1},dc = {1, 0, -1, 0}; start at(0, 0), direction0.- Repeat
m ยท ntimes:- Add
matrix[r][c], mark visited. - Compute the next cell; if it is invalid or visited, turn:
d = (d + 1) % 4. - Move to the next cell in direction
d.
- Add
Visualization
1 โ 2 โ 3
โ
4 โ 5 6 the walker turns at the wall (3), at the wall (9),
โ โ at the wall (7), and at the visited cell (1),
7 โ 8 โ 9 then at visited 6 after reaching 5.
output: 1 2 3 6 9 8 7 4 5Code
import java.util.*;
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[] dr = {0, 1, 0, -1}; // right, down, left, up
int[] dc = {1, 0, -1, 0};
boolean[][] visited = new boolean[m][n];
List<Integer> result = new ArrayList<>();
int r = 0, c = 0, d = 0;
for (int step = 0; step < m * n; step++) {
result.add(matrix[r][c]);
visited[r][c] = true;
int nr = r + dr[d], nc = c + dc[d];
if (nr < 0 || nr >= m || nc < 0 || nc >= n || visited[nr][nc]) {
d = (d + 1) % 4; // blocked: turn clockwise
nr = r + dr[d];
nc = c + dc[d];
}
r = nr;
c = nc;
}
return result;
}
}Complexity
- Time: O(m ยท n) โ one step per cell.
- Space: O(m ยท n) โ the
visitedarray.
Layer-by-Layer BoundariesOptimal
TimeO(m ยท n)SpaceO(1)Intuition
Instead of remembering every visited cell, remember only the four walls of the unvisited rectangle. Walk the top row and push top down; walk the right column and pull right in; then โ only if rows remain โ walk the bottom row backwards and lift bottom; and โ only if columns remain โ walk the left column upward and push left in.
Algorithm
top = 0,bottom = m - 1,left = 0,right = n - 1.- While
top <= bottom && left <= right:- For
cinleft..right: addmatrix[top][c]; thentop++. - For
rintop..bottom: addmatrix[r][right]; thenright--. - If
top <= bottom: forcinright..left(descending): addmatrix[bottom][c];bottom--. - If
left <= right: forrinbottom..top(descending): addmatrix[r][left];left++.
- For
Visualization
flowchart TD
A["T=0 B=2 L=0 R=3<br/>top row โ 1 2 3 4"] --> B1["T=1<br/>right col โ 8 12"]
B1 --> C["R=2<br/>bottom row โ 11 10 9"]
C --> D["B=1<br/>left col โ 5"]
D --> E["L=1 T=1 B=1 R=2<br/>top row โ 6 7"]
E --> F["T=2 > B=1<br/>skip bottom and stop"]Code
import java.util.*;
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = 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++) result.add(matrix[top][c]); // โ
top++;
for (int r = top; r <= bottom; r++) result.add(matrix[r][right]); // โ
right--;
if (top <= bottom) { // a row is still left to walk backwards
for (int c = right; c >= left; c--) result.add(matrix[bottom][c]); // โ
bottom--;
}
if (left <= right) { // a column is still left to walk upwards
for (int r = bottom; r >= top; r--) result.add(matrix[r][left]); // โ
left++;
}
}
return result;
}
}Complexity
- Time: O(m ยท n) โ every element is added exactly once.
- Space: O(1) โ only four indices (output excluded).
Complexity Comparison
| Approach | Time | Space (extra) |
|---|---|---|
| Simulation + visited | O(m ยท n) | O(m ยท n) |
| Boundaries | O(m ยท n) | O(1) |
Common Pitfalls
- Omitting the
top <= bottom/left <= rightchecks โ a single remaining row (e.g.[[1,2,3]]) gets read twice, forward and backward. - Updating a wall before its loop instead of after it, shifting the walked row/column by one.
- Assuming the matrix is square โ test
1 x n,m x 1and3 x 4shapes. - In the simulation, turning only on out-of-bounds and forgetting the visited check โ the walker re-enters the outer ring.