Spiral Matrix II: Filling a Matrix in Spiral Order
Given a positive integer n, generate an n x n matrix filled with elements from 1 to n * n in spiral order. For n = 3, the output is [[1,2,3],[8,9,4],[7,6,5]].
This is LeetCode 59: Spiral Matrix II. If you have already solved Spiral Matrix (LeetCode 54), you will recognize the same structure here. The difference is that instead of reading values from an existing matrix, you are writing values into an empty one. The boundary-shrinking technique carries over almost unchanged.
The approach
You start with an empty n x n grid and a counter starting at 1. Then you walk the spiral path, placing the counter value into each cell and incrementing it. The path follows the same four-phase loop used in Spiral Matrix I:
- Right across the
toprow, fromlefttoright. Then incrementtop. - Down the
rightcolumn, fromtoptobottom. Then decrementright. - Left across the
bottomrow, fromrighttoleft. Then decrementbottom. - Up the
leftcolumn, frombottomtotop. Then incrementleft.
You maintain four boundary variables (top, bottom, left, right) that start at the edges of the matrix and shrink inward after each traversal. When the boundaries cross, every cell has been filled and you stop.
Because the matrix is always square (n x n), you do not need the extra boundary checks that Spiral Matrix I requires for non-square matrices. Every layer is a perfect square ring, and the inner layers shrink symmetrically.
The only change from Spiral Matrix I is the operation per cell. Reading becomes writing. The boundary logic is identical. If you can type the boundary-shrinking skeleton from memory, this problem is just plugging in an assignment instead of an append.
The solution
def generateMatrix(n: int) -> list[list[int]]:
matrix = [[0] * n for _ in range(n)]
top, bottom = 0, n - 1
left, right = 0, n - 1
num = 1
while top <= bottom and left <= right:
for col in range(left, right + 1):
matrix[top][col] = num
num += 1
top += 1
for row in range(top, bottom + 1):
matrix[row][right] = num
num += 1
right -= 1
for col in range(right, left - 1, -1):
matrix[bottom][col] = num
num += 1
bottom -= 1
for row in range(bottom, top - 1, -1):
matrix[row][left] = num
num += 1
left += 1
return matrix
Walkthrough
Let's trace the algorithm on n = 3 step by step. The matrix starts as all zeros, and the counter num starts at 1.
Step 1: Fill top row, left to right.
top=0, bottom=2, left=0, right=2
Place 1, 2, 3. Then top += 1.
Step 2: Fill right column, top to bottom.
top=1, bottom=2, left=0, right=2
Place 4, 5. Then right -= 1.
Step 3: Fill bottom row, right to left.
top=1, bottom=2, left=0, right=1
Place 6, 7. Then bottom -= 1.
Step 4: Fill left column, bottom to top.
top=1, bottom=1, left=0, right=1
Place 8. Then left += 1.
Step 5: New layer. Fill the center cell.
top=1, bottom=1, left=1, right=1
Place 9. Then top += 1. Now top > bottom, so the loop ends.
Step 6: All cells filled. Done!
top=2, bottom=1, left=1, right=1
Result: [[1,2,3],[8,9,4],[7,6,5]]
In step 1, the top row fills with 1, 2, 3 and top moves from 0 to 1. In step 2, the right column fills downward with 4, 5 and right moves from 2 to 1. Step 3 fills the bottom row leftward with 6, 7 and bottom moves from 2 to 1. Step 4 fills the left column upward with 8 and left moves from 0 to 1.
At that point, all four boundaries point to the single center cell. The loop runs one more time: the "right" traversal places 9, top increments to 2, and now top > bottom so the while condition fails. The matrix is complete.
Notice that num ends at 10, which is n * n + 1. Every value from 1 to 9 has been placed exactly once.
Complexity
| Metric | Value |
|---|---|
| Time | O(n^2) |
| Space | O(n^2) |
Time: you visit each of the n * n cells exactly once. Each visit does O(1) work (one assignment, one increment). Total: O(n^2).
Space: the output matrix itself takes O(n^2). Beyond that, you only use the four boundary variables and the counter, which is O(1) extra space.
Building blocks
This problem is built on two reusable pieces that CodeBricks drills independently:
Boundary-layer traversal
The pattern of maintaining four boundary variables and peeling off one rectangular layer at a time:
top, bottom = 0, n - 1
left, right = 0, n - 1
while top <= bottom and left <= right:
# process outer layer
# shrink boundaries inward
This skeleton appears in Spiral Matrix I, Spiral Matrix II, Rotate Image, and any problem that processes a matrix from the outside in. The specific operation per cell changes, but the boundary management stays the same.
Direction cycling
The four-phase loop (right, down, left, up) with boundary adjustment after each phase. The order never changes. Each direction uses the current boundary values, and each direction advances exactly one boundary. Internalizing this cycle means you never have to think about which boundary to adjust or which direction comes next.
Edge cases
n = 1: the matrix is [[1]]. The while loop runs once, the "right" traversal places 1, top increments past bottom, and the loop ends. No special handling needed.
n = 2: the matrix is [[1,2],[4,3]]. One full pass through all four directions fills all four cells. The right traversal places 1 and 2. The down traversal places 3. The left traversal places 4. The up traversal range is empty (since bottom has already moved past top). The boundaries cross and the loop ends.
From understanding to recall
You have read through the solution and seen how the four boundaries control the spiral path. The logic is clean: four for loops, four boundary adjustments, one counter. But can you type it from scratch when you are staring at a blank editor?
The details that trip people up under pressure are small: which boundary increments and which decrements, the + 1 and - 1 in the range calls, the reverse range syntax for going left and up. These are not conceptual gaps. They are recall details that fade without practice.
Spaced repetition locks them in. You write the boundary setup, the four traversals, and the counter logic from memory. You do it today, again in two days, again in five. After a few reps, you see "generate spiral matrix" and the code flows out automatically. No hesitation, no off-by-one fumbling.
Related posts
- Spiral Matrix - The reading version of this same boundary-shrinking technique, with the extra guard checks for non-square matrices
- Rotate Image - Another layer-by-layer matrix problem where you process concentric rings from the outside in
CodeBricks breaks Spiral Matrix II into its boundary-layer-traversal and direction-cycling building blocks, then drills them independently with spaced repetition. You type the four-boundary setup, the four fill loops, and the counter logic from scratch until the pattern is automatic. When a spiral generation problem shows up in your interview, you do not think about it. You just write it.