Spiral Matrix
Medium · Math & Geometry · Explanation and code example
Iteration (Optimal)
How it works
We want to read the matrix in spiral order: right → down → left → up, repeating.
Instead of keeping four boundaries (top, bottom, left, right), this approach tracks:
- the current direction (right, down, left, up)
- how many steps we can take in the current direction before turning
Key idea:
- Spiral traversal alternates between moving along a row length and a column length
- first we move right
colssteps - then down
rows - 1steps - then left
cols - 1steps - then up
rows - 2steps - and so on...
- first we move right
- After completing a direction, the available steps in that “dimension” shrink by 1.
We store the remaining step counts in an array:
steps[0]= how many moves left in the horizontal directionsteps[1]= how many moves left in the vertical direction
d & 1 tells us whether the current direction is horizontal (0) or vertical (1).
Steps
- Create a list of direction vectors in clockwise order:
- right
(0, 1), down(1, 0), left(0, -1), up(-1, 0)
- right
- Initialize step counts:
steps[0] = number of columnssteps[1] = number of rows - 1
- Start just outside the matrix at
(r, c) = (0, -1)so the first move goes into(0, 0). - Set direction index
d = 0(start moving right). - While the current step count
steps[d & 1]is greater than0:- Move
steps[d & 1]times in directiond:- update
(r, c)by the direction vector - append
matrix[r][c]to the result
- update
- After finishing those moves, shrink the step count for that dimension:
steps[d & 1] -= 1
- Turn to the next direction:
d = (d + 1) % 4
- Move
- Return the result list.
Complexity
- Time complexity:
O(m * n) - Space complexity:
O(1)extra space.O(m * n)space for the output list.
Where
mis the number of rows andnis the number of columns.
Things to watch for
Not Checking Boundaries After Each Direction
After completing a horizontal traversal, the vertical bounds may have crossed (or vice versa). Failing to check left < right && top < bottom before the third and fourth directions causes duplicate elements to be added when the matrix reduces to a single row or column.
Mishandling Non-Square Matrices
Rectangular matrices with significantly different row and column counts can cause issues if the algorithm assumes square behavior. The spiral may terminate early or add extra elements if boundary checks do not account for both dimensions independently.
Incorrect Direction Rotation
When using direction vectors, rotating incorrectly (e.g., counterclockwise instead of clockwise, or incorrect sign changes) produces a non-spiral traversal pattern. The correct clockwise rotation transforms (dr, dc) to (dc, -dr).
Python code example
from typing import List
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
res = []
directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
steps = [len(matrix[0]), len(matrix) - 1]
r, c, d = 0, -1, 0
while steps[d & 1]:
for i in range(steps[d & 1]):
r += directions[d][0]
c += directions[d][1]
res.append(matrix[r][c])
steps[d & 1] -= 1
d += 1
d %= 4
return res
C++ code example
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> res;
vector<pair<int, int>> directions = {{0, 1}, {1, 0},
{0, -1}, {-1, 0}};
vector<int> steps = {static_cast<int>(matrix[0].size()), static_cast<int>(matrix.size()) - 1};
int r = 0, c = -1, d = 0;
while (steps[d % 2]) {
for (int i = 0; i < steps[d % 2]; i++) {
r += directions[d].first;
c += directions[d].second;
res.push_back(matrix[r][c]);
}
steps[d % 2]--;
d = (d + 1) % 4;
}
return res;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.