LeetCode “Spiral Matrix” (#54) asks you to return all the elements of an m × n matrix in clock-wise spiral order, starting from the top-left corner.
Example
Input[[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]
Output[1, 2, 3, 6, 9, 8, 7, 4, 5]
Think of tracing the outer frame of the matrix, then peeling it away layer by layer—just like unwrapping an onion.
Here’s the [Problem Link] to begin with.
Optimal Solution (Pointer Shrinking Technique)
Intuition and Approach
- Four Pointers mark the current “unvisited rectangle”:
top
row,bottom
row,left
column,right
column. - Repeatedly walk the perimeter of that rectangle in four mini-passes:
- Left ➜ Right across the top row.
- Top ➜ Bottom down the right column.
- Right ➜ Left across the bottom row (if any rows remain).
- Bottom ➜ Top up the left column (if any cols remain).
- After completing the loop, shrink the rectangle:
incrementtop
, decrementbottom
, incrementleft
, decrementright
. - Stop when
top > bottom
orleft > right
.
Because every element is touched exactly once and we reuse the result list for output, the algorithm runs in O(m·n)
time with O(1)
extra space.
Code Implementation
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
# Handle empty input
if not matrix or not matrix[0]:
return []
result = [] # stores the spiral order
# Initialize boundary pointers
top, left = 0, 0
bottom, right = len(matrix) - 1, len(matrix[0]) - 1
# Continue until the boundaries cross
while top <= bottom and left <= right:
# Traverse the top row from left to right
for i in range(left, right + 1):
result.append(matrix[top][i])
top += 1 # top row is done
# Traverse the right column from top to bottom
for i in range(top, bottom + 1):
result.append(matrix[i][right])
right -= 1 # right column is done
# Traverse the bottom row from right to left (if any)
if top <= bottom:
for i in range(right, left - 1, -1):
result.append(matrix[bottom][i])
bottom -= 1 # bottom row is done
# Traverse the left column from bottom to top (if any)
if left <= right:
for i in range(bottom, top - 1, -1):
result.append(matrix[i][left])
left += 1 # left column is done
return result
Code Explanation
- Boundaries:
top
,bottom
,left
, andright
fence in the part of the matrix we still need to visit. - Perimeter Walk: Each loop iteration captures one “ring” of the onion in four straight passes.
- Boundary Update: After finishing a side, we move the corresponding pointer inward so we don’t revisit those cells.
- Termination: When the pointers cross, no unvisited cells remain.
Dry Run (3 × 3 Matrix)
Step | top | bottom | left | right | Elements Added | result after step |
---|---|---|---|---|---|---|
1 | 0 | 2 | 0 | 2 | 1 2 3 (top row) | 1 2 3 |
2 | 1 | 2 | 0 | 2 | 6 9 (right column) | 1 2 3 6 9 |
3 | 1 | 2 | 0 | 1 | 8 7 (bottom row) | 1 2 3 6 9 8 7 |
4 | 1 | 1 | 0 | 1 | 4 (left column) | 1 2 3 6 9 8 7 4 |
5 | 1 | 1 | 1 | 1 | 5 (final center element) | 1 2 3 6 9 8 7 4 5 |
Pointers cross, done!
Time and Space Complexity
- Time:
O(m × n)
– every cell is visited exactly once. - Space:
O(1)
extra – aside from the output list, only four integer pointers are used.
Conclusion
Using four shrinking boundaries lets us capture the Spiral Matrix order cleanly, without auxiliary grids or markers. This pattern—peel the outer layer, shrink, repeat—is a handy template for many 2-D traversal problems.
For any changes to the article, kindly email at code@codeanddebug.in or contact us at +91-9712928220.