Spiral Matrix
Given an m x n matrix, return all elements of the matrix in spiral order : starting at the top-left corner, walk across the top row, down the right column, across the bottom row, and up the left column, then shrink inward and repeat. Track four moving boundaries (top, bottom, left, right) and peel off one full ring of the matrix per lap, tightening the boundaries after each side.
Constraints
- m == matrix.length
- n == matrixi.length
- 1 ≤ m, n ≤ 10
- -100 ≤ matrixi[j] ≤ 100
Example
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]][1, 2, 3, 6, 9, 8, 7, 4, 5]Explanation Walk the top row left-to-right, the right column top-to-bottom, the bottom row right-to-left, the left column bottom-to-top, then spiral into the single remaining center cell.
In plain terms
- Boundaries
- The four edges of the part of the matrix not yet visited — they shrink inward by one every time a side is fully walked.
Peel off one ring at a time, shrinking inward
Walk the top row: push 1, 2, 3. Move the top boundary down.
What happens in this step
top=0, bottom=2, left=0, right=2 Walk columns 0..2 of row 0: push 1, 2, 3 result = [1, 2, 3] top becomes 1
Steps to visualize
- Walk the top row from the left boundary to the right boundary, then move the top boundary down.
- Walk the right column from the new top boundary to the bottom boundary, then move the right boundary in.
- If a row remains, walk the bottom row from the right boundary to the left boundary, then move the bottom boundary up.
- If a column remains, walk the left column from the bottom boundary to the top boundary, then move the left boundary in.
- Repeat until the boundaries cross — every cell has now been visited exactly once.
Walk through the code
Same walkthrough, now with the code. Press Next to move one step and watch which lines run.
Walk the top row: push 1, 2, 3. Move the top boundary down.
What happens in this step
top=0, bottom=2, left=0, right=2 Walk columns 0..2 of row 0: push 1, 2, 3 result = [1, 2, 3] top becomes 1
Solution
function spiralOrder(matrix) {
const result = [];
let top = 0;
let bottom = matrix.length - 1;
let left = 0;
let right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
for (let col = left; col <= right; col++) {
result.push(matrix[top][col]);
}
top++;
for (let row = top; row <= bottom; row++) {
result.push(matrix[row][right]);
}
right--;
if (top <= bottom) {
for (let col = right; col >= left; col--) {
result.push(matrix[bottom][col]);
}
bottom--;
}
if (left <= right) {
for (let row = bottom; row >= top; row--) {
result.push(matrix[row][left]);
}
left++;
}
}
return result;
}- Time
- O(m * n)
- Space
- O(1) (excluding the output array)
Test cases
| Input | Expected | Covers |
|---|---|---|
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] | [1, 2, 3, 6, 9, 8, 7, 4, 5] | example from the docstring |
matrix = [[1]] | [1] | smallest valid input: a single cell |
matrix = [[1, 2, 3, 4]] | [1, 2, 3, 4] | a matrix with only one row |
matrix = [[1], [2], [3]] | [1, 2, 3] | a matrix with only one column |
matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] | [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7] | a rectangular matrix with more columns than rows |
matrix = [[1, 2], [3, 4]] | [1, 2, 4, 3] | smallest matrix that actually turns a corner |