49. Spiral Matrix
mediumAsked at SalesforceReturn all elements of a matrix in spiral order. Salesforce uses this to test boundary tracking and clean iteration when corners get tricky.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Salesforce loops.
- Glassdoor (2026-Q1)— Salesforce uses this to test matrix-boundary off-by-one debugging.
- Blind (2025)— Common pairing with LC 48 (rotate image).
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. Direction array with visited tracking
Move in directions right, down, left, up cyclically; mark visited cells.
- Time
- O(m*n)
- Space
- O(m*n)
function spiralOrder(matrix) {
const m = matrix.length, n = matrix[0].length;
const visited = Array.from({ length: m }, () => new Array(n).fill(false));
const dirs = [[0,1],[1,0],[0,-1],[-1,0]];
let d = 0, r = 0, c = 0;
const result = [];
for (let i = 0; i < m * n; i++) {
result.push(matrix[r][c]);
visited[r][c] = true;
const nr = r + dirs[d][0], nc = c + dirs[d][1];
if (nr < 0 || nr >= m || nc < 0 || nc >= n || visited[nr][nc]) {
d = (d + 1) % 4;
}
r += dirs[d][0]; c += dirs[d][1];
}
return result;
}Tradeoff: Works but uses O(m*n) extra space.
2. Shrinking bounds
Maintain top/bottom/left/right boundaries. Walk one side, shrink the relevant boundary, rotate. Stop when bounds cross.
- Time
- O(m*n)
- Space
- O(1)
function spiralOrder(matrix) {
const result = [];
let top = 0, bottom = matrix.length - 1, left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
for (let c = left; c <= right; c++) result.push(matrix[top][c]); top++;
for (let r = top; r <= bottom; r++) result.push(matrix[r][right]); right--;
if (top <= bottom) for (let c = right; c >= left; c--) result.push(matrix[bottom][c]); bottom--;
if (left <= right) for (let r = bottom; r >= top; r--) result.push(matrix[r][left]); left++;
}
return result;
}Tradeoff: O(1) extra space. The if-guards on the third and fourth loops prevent double-counting on single-row or single-column residuals.
Salesforce-specific tips
Salesforce specifically grades on the if-guards in the third and fourth direction loops — without them, single-row residuals get duplicated. Bonus signal: explain WHEN the guard fires (when the matrix has shrunk to a single row or column).
Common mistakes
- Forgetting the guards on the last two loops — duplicates elements on non-square matrices.
- Not updating bounds AFTER the loop — wrong starting row/column.
- Confusing m and n — matrix.length is rows (m), matrix[0].length is cols (n).
Follow-up questions
An interviewer at Salesforce may pivot to one of these next:
- Spiral Matrix II (LC 59) — fill an n x n matrix in spiral order.
- Spiral Matrix III (LC 885) — spiral with a starting point.
- Diagonal Traverse (LC 498).
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
Why the guards on the last two loops?
After walking right and down, top may exceed bottom (single row consumed). Walking left/up again would duplicate. The guards detect this and skip.
Could I do this recursively?
Yes — recurse on the inner sub-matrix after walking the outer ring. Iterative is more memory-efficient.
Practice these live with InterviewChamp.AI
Drill Spiral Matrix and other Salesforce interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →