54. Spiral Matrix
mediumAsked at MicrosoftSpiral Matrix is Microsoft's most-asked matrix-traversal question. The interviewer is grading whether you can manage four shrinking boundaries (top, bottom, left, right) without an off-by-one bug at the moment two boundaries cross in the middle of a row or column.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Microsoft loops.
- Glassdoor (2026-Q1)— Microsoft L60/L61 onsite reports list this as the canonical 30-minute matrix-traversal screen.
- Levels.fyi (2025-12)— Microsoft new-grad interview compilation flags Spiral Matrix as the most-repeated 2D-array question.
Problem
Given an m x n matrix, return all elements of the matrix in spiral order.
Constraints
m == matrix.lengthn == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
Examples
Example 1
matrix = [[1,2,3],[4,5,6],[7,8,9]][1,2,3,6,9,8,7,4,5]Example 2
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]Approaches
1. Four-boundary shrink (optimal)
Track top, bottom, left, right boundaries. Walk right along top, down along right, left along bottom (if rows remain), up along left (if cols remain). Shrink the boundaries each layer.
- Time
- O(m*n)
- Space
- O(1) excluding output
function spiralOrder(matrix) {
const result = [];
if (!matrix.length) return 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 j = left; j <= right; j++) result.push(matrix[top][j]);
top++;
for (let i = top; i <= bottom; i++) result.push(matrix[i][right]);
right--;
if (top <= bottom) {
for (let j = right; j >= left; j--) result.push(matrix[bottom][j]);
bottom--;
}
if (left <= right) {
for (let i = bottom; i >= top; i--) result.push(matrix[i][left]);
left++;
}
}
return result;
}Tradeoff: Single pass over every cell. The two if-guards (top <= bottom and left <= right) are the entire bug surface — they prevent re-traversing a single remaining row or column in the middle of the spiral.
2. Direction-vector with visited matrix
Maintain a direction index 0..3 cycling through right/down/left/up. Turn when the next cell is out of bounds or already visited.
- Time
- O(m*n)
- Space
- O(m*n)
function spiralOrder(matrix) {
if (!matrix.length) return [];
const m = matrix.length;
const n = matrix[0].length;
const seen = Array.from({ length: m }, () => Array(n).fill(false));
const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]];
let d = 0;
let r = 0;
let c = 0;
const result = [];
for (let k = 0; k < m * n; k++) {
result.push(matrix[r][c]);
seen[r][c] = true;
const nr = r + dirs[d][0];
const nc = c + dirs[d][1];
if (nr < 0 || nr >= m || nc < 0 || nc >= n || seen[nr][nc]) {
d = (d + 1) % 4;
}
r += dirs[d][0];
c += dirs[d][1];
}
return result;
}Tradeoff: Easier to reason about for beginners but pays O(m*n) extra space for the visited matrix. Microsoft interviewers prefer the four-boundary version; they specifically ask 'can you do it without the visited array?'
Microsoft-specific tips
Microsoft cares about how you handle the leftover middle row/column when the matrix has an odd dimension or is non-square. Walk through the 3x4 example out loud: 'after the first three sides, top has advanced past bottom — I need a guard before walking left across the bottom row.' If you trace that case before writing code, the bug never appears.
Common mistakes
- Forgetting the top <= bottom check before the bottom-row scan — re-visits a row in 1-row leftover cases.
- Forgetting the left <= right check before the left-column scan — re-visits a column.
- Going out of bounds when m == 1 or n == 1 (a single row or column should still print every element exactly once).
Follow-up questions
An interviewer at Microsoft may pivot to one of these next:
- Spiral Matrix II (LC 59) — generate an n x n matrix in spiral order with values 1..n^2.
- Spiral Matrix III (LC 885) — start in the middle, spiral outward from an arbitrary cell.
- Rotate Image (LC 48) — same boundary-shrink mental model.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why two if-guards in the middle of the loop?
Once top crosses bottom, walking left along the bottom row would revisit cells from the previous top row. The guard prevents that. Same for left/right when walking up.
Should I use the boundary approach or the direction-vector approach?
Microsoft will accept either but explicitly prefers no extra space. Lead with the four-boundary version; mention the direction-vector exists if asked to compare.
Free learning resources
Curated free links for this problem.
Practice these live with InterviewChamp.AI
Drill Spiral Matrix and other Microsoft interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →