Skip to main content

54. Spiral Matrix

mediumAsked at Cisco

Spiral Matrix at Cisco is a matrix-traversal problem that tests index arithmetic under pressure. The interviewer is checking whether you maintain the four boundaries (top/bottom/left/right) and shrink them after each side rather than juggling four separate loop variables.

By Alex Chen, Founder, InterviewChamp.AI · Last verified

Source citations

Public interview reports confirming this problem appears in Cisco loops.

  • Glassdoor (2026-Q1)Cisco SDE-II onsite reports cite Spiral Matrix as a 30-minute matrix-traversal round.
  • Blind (2025-10)Cisco interview thread lists Spiral Matrix as a recurring matrix problem.

Problem

Given an m x n matrix, return all elements of the matrix in spiral order. The traversal starts at the top-left corner, moves right across the top row, down the right column, left across the bottom row, up the left column, and continues inward.

Constraints

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

Examples

Example 1

Input
matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output
[1,2,3,6,9,8,7,4,5]

Example 2

Input
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
Output
[1,2,3,4,8,12,11,10,9,5,6,7]

Approaches

1. Direction-vector with visited set

Step one cell at a time using a direction vector. Turn right (rotate the direction) when you hit a wall or a visited cell.

Time
O(m * n)
Space
O(m * n)
function spiralOrderDir(matrix) {
  if (!matrix.length) return [];
  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: Clear logic, easy to extend (spiral counterclockwise, different starting corner). Allocates O(m*n) for the visited matrix. Cisco interviewers accept it; the boundary-shrinking version below is more elegant and uses O(1) extra space.

2. Four-boundary shrink (optimal)

Maintain top/bottom/left/right boundaries. Walk top-row left-to-right then top++; walk right-col top-to-bottom then right--; walk bottom-row right-to-left then bottom--; walk left-col bottom-to-top then left++. Stop when top > bottom or left > right.

Time
O(m * n)
Space
O(1) excluding output
function spiralOrder(matrix) {
  const result = [];
  if (!matrix.length) return result;
  let top = 0, bottom = matrix.length - 1;
  let 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: Zero extra space, four clean loops. The two `if (top <= bottom)` and `if (left <= right)` guards are the gotcha — without them, a single-row or single-column residual gets traversed twice. Cisco interviewers EXPECT these guards.

Cisco-specific tips

Cisco interviewers grade this on the boundary-shrink pattern. State out loud: 'I maintain four boundaries — top, bottom, left, right — and walk one side at a time, shrinking the boundary after each side. The middle two loops need a guard because a single row/column can otherwise be double-counted.' That sentence is the whole interview signal. Draw the spiral on the whiteboard before writing code so the interviewer can see you understand the four-direction pattern.

Common mistakes

  • Forgetting the `if (top <= bottom)` guard on the third loop — for a single-row matrix you walk top row left-to-right then try to walk bottom row right-to-left, which is the same row visited again.
  • Using `<` instead of `<=` in the loop bounds — off-by-one misses the last cell of each side.
  • Allocating a visited matrix when boundary-shrink already gives you O(1) space — wastes memory unnecessarily.

Follow-up questions

An interviewer at Cisco may pivot to one of these next:

  • Spiral Matrix II (LC 59) — fill an n x n matrix with 1..n^2 in spiral order. Same algorithm, write instead of read.
  • Spiral Matrix III (LC 885) — start from arbitrary cell and walk in a virtual spiral past the bounds.
  • What if the matrix can be empty or rectangular but not square? (Same algorithm — `m != n` is fine.)

Solve it now

Free. No sign-up. Python and JavaScript run instantly in your browser.

Output

Press Run or Cmd+Enter to execute

FAQ

Why two guards but only on the bottom and left passes?

Because after walking the top row (top++) and the right column (right--), the residual might be a single row or single column. The bottom-row walk uses the (new) `top`, so if top > bottom (single row was already walked), skip it. Same for the left-column walk after top and bottom were processed.

Is the direction-vector version ever preferred?

Yes when the spiral isn't standard — counterclockwise, starts from middle, walks past bounds (LC 885). The visited-cell turn condition generalizes. For the vanilla LC 54, boundary-shrink is the cleaner answer.

Free learning resources

Curated free links for this problem.

Practice these live with InterviewChamp.AI

Drill Spiral Matrix and other Cisco interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.

Practice these live with InterviewChamp.AI →