AlgoMaster Logo

Spiral Matrix

Last Updated: March 22, 2026

medium
4 min read

Understanding the Problem

Traversing a matrix in spiral order is one of those problems that sounds simple when you hear it but trips people up the moment they start coding. There's no clever algorithm or data structure trick here. It's pure simulation, and the challenge is managing boundaries and direction changes without introducing off-by-one errors.

Picture yourself walking through the matrix like a maze, always hugging the outer wall. You start at the top-left corner and move right. When you hit the edge (or a cell you've already visited), you turn clockwise: right becomes down, down becomes left, left becomes up, up becomes right again. You keep walking and turning until every cell has been visited.

The key question is: how do we know when to turn, and how do we make sure we don't visit a cell twice? There are two clean ways to handle this, and both give us the same result with different trade-offs.

Key Constraints:

  • m, n <= 10 means the matrix has at most 100 elements. Any algorithm works here. The problem isn't about performance, it's about correctness.
  • Values range from -100 to 100, so there's no overflow concern.
  • Both solutions run in O(m * n), which is optimal since we must visit every cell exactly once. The focus here is writing clean, bug-free code.

Approach 1: Simulation with Direction Arrays

Intuition

The most natural way to think about this problem is to literally simulate the spiral walk. You're at some position in the matrix, moving in some direction. When you can't keep going (either you'd go out of bounds or step on an already-visited cell), you turn clockwise and continue.

To implement this, we use a visited matrix to track which cells we've been to, and a direction array to cycle through right, down, left, up. When the next cell in our current direction is invalid, we rotate to the next direction.

Algorithm

  1. Create a visited boolean matrix of the same size, initialized to false.
  2. Define direction vectors: {0,1} (right), {1,0} (down), {0,-1} (left), {-1,0} (up).
  3. Start at position (0, 0) with direction index 0 (right).
  4. For each of the m * n steps:
    1. Add the current cell's value to the result and mark it as visited.
    2. Compute the next position using the current direction.
    3. If the next position is out of bounds or already visited, rotate the direction index clockwise (increment mod 4), then recompute the next position.
    4. Move to the next position.
  5. Return the result list.

Code

The simulation approach works perfectly and is easy to reason about. But notice the visited matrix: we're allocating an entire m x n boolean grid just to remember where we've been. Is there a way to know which cells are "available" without tracking each one individually? What if, instead of marking individual cells, we tracked the boundaries of the unvisited region and shrank them as we go?

Approach 2: Layer-by-Layer (Boundary Shrinking)

Intuition

Instead of simulating each step and checking a visited matrix, think about the spiral as a series of rectangular layers. The outermost layer is the border of the matrix. Once we've traversed it, the remaining matrix is a smaller rectangle. We peel off one layer at a time, moving inward.

To implement this, we maintain four boundary variables: top, bottom, left, right. Each layer traversal follows four sweeps:

  1. Traverse the top row from left to right, then push top down.
  2. Traverse the right column from top to bottom, then push right left.
  3. Traverse the bottom row from right to left (if rows remain), then push bottom up.
  4. Traverse the left column from bottom to top (if columns remain), then push left right.

The critical detail is those "if" checks on steps 3 and 4. After moving top down and right left, the boundaries might have crossed, meaning there's no bottom row or left column to traverse in this layer. This happens with single-row or single-column matrices.

Algorithm

  1. Initialize top = 0bottom = m - 1left = 0right = n - 1.
  2. While top <= bottom and left <= right:
    1. Traverse the top row: for col from left to right, add matrix[top][col]. Increment top.
    2. Traverse the right column: for row from top to bottom, add matrix[row][right]. Decrement right.
    3. If top <= bottom: traverse the bottom row from right to left, add matrix[bottom][col]. Decrement bottom.
    4. If left <= right: traverse the left column from bottom to top, add matrix[row][left]. Increment left.
  3. Return the result list.

Code