← DSA Atlas
Dedicated problem page · #54

Spiral Matrix

MediumMatrix and SimulationShrinking boundary walkBoundary pointers (simulation)
Solve on LeetCode ↗
54
MediumMatrix and SimulationBoundary pointers (simulation)Shrinking boundary walk

Spiral Matrix

Given an m x n matrix, return all its elements in spiral order, starting from the top-left corner and moving right, down, left, and up, spiraling inward.

Open official problem prompt ↗
In plain English

Read out every element exactly once following the clockwise inward spiral.

Picture it like this

Like peeling an onion or unwinding a coil: you strip off the outer ring, then the next ring in, until nothing is left.

Example
Input
matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output
[1,2,3,6,9,8,7,4,5]
Why
Walking the outer ring clockwise gives 1,2,3,6,9,8,7,4 and the lone center cell 5 finishes the spiral.
Constraints
m == matrix.lengthn == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
Pattern lesson

See the pattern, then code

Shrinking boundary walk
Recognition clue

Being asked to output every cell in spiral / clockwise order points to tracking four moving boundaries (top, bottom, left, right) and peeling one layer at a time.

Matrix and Simulation

Rotations, boundary walks, direction changes, or careful in-place state updates.. Keep four walls. Traverse the top row, then the right column, then the bottom row, then the left column, and after each pass move that wall inward. Repeat until the walls cross.

New words, made simpleKnow these before the algorithm
Boundary pointer
An index marking the current top, bottom, left, or right edge of the unvisited region.
Layer / ring
One complete loop around the current rectangular boundary.
Inward shrink
Moving a boundary after its row or column is consumed.
Approaches from first idea to best ideaCompare the trade-offs
ApproachHow it thinksCost
Direction vectors with visited set

Works but needs an extra visited grid or in-place marking.

Turn right whenever the next cell is out of bounds or already seen.

Time O(m*n)Space O(m*n)
The rule we keep true

Invariant

top, bottom, left, right always bound the rectangle of cells not yet appended; every cell inside is still to be visited.

Why this is correct

Reasoning

Each of the four passes appends an entire current edge exactly once and then retracts that edge, so no cell is visited twice and the loop stops precisely when the region is empty. The two inner guards prevent re-traversing a row or column when the rectangle has collapsed to a single line.

The algorithm in three movesSay these aloud before coding
1Initialize top, bottom, left, right to the matrix edges and an empty result

top row: 1,2,3 (top->1)

2Go left-to-right along top, then increment top

right col: 6,9 (right->1)

3Go top-to-bottom along right, then decrement right

bottom row: 8,7 (bottom->1)

4If rows remain, go right-to-left along bottom and decrement bottom; if columns remain, go bottom-to-top along left and increment left

left col: 4 (left->1); center: 5

5Repeat while top <= bottom and left <= right

Visual trace

Follow the data, one decision at a time

Input snapshotHighlighted cells are involved in this example
10
21
32
63
94
85
76
47
58
1 · Readrow 0
2 · Askleft..right?
3 · Update statetop=0
4 · Resultappend 1,2,3; top=1
Key takeaway

The output cells listed in the clockwise spiral order they are collected.

Code walkthrough

Read the solution in small chunks

Python 3

Do not memorize the whole program. Connect each group of lines to one job in the algorithm.

  1. 1
    Lines 6-9Top edge and right edge

    Always safe on entry because the while guard ensures a non-empty rectangle; shrink top then right.

  2. 2
    Lines 12-15Guarded bottom edge

    The if top <= bottom check avoids re-reading a row already consumed when the rectangle is one row tall.

  3. 3
    Lines 16-19Guarded left edge

    The if left <= right check avoids re-reading a single remaining column.

Make it stick

Edge cases, mistakes, and one self-check

E

Edge cases to test

  • Single row (1 x n)
  • Single column (m x 1)
  • Non-square rectangular matrices
  • 1 x 1 matrix
!

Common beginner mistakes

  • Omitting the inner top<=bottom / left<=right guards, which double-counts cells in thin matrices
  • Reading matrix[0] length without handling that all rows share it (they do per constraints)
  • Off-by-one in the reverse ranges for the bottom and left passes
Check your understanding

Why are the bottom and left passes guarded but not the top and right passes?