Menu

Earn Premium with Referrals

Invite your friends and earn Premium rewards through our referral program.

See how it works and start inviting friends.

Spiral Matrix
DSA

Spiral Matrix

Understand how to traverse or construct a matrix in spiral order using controlled boundaries.

Spiral Matrix processes a matrix layer by layer, walking the outer boundary then moving inward:

Top → Right → Bottom → Left → Shrink → Repeat

Focus on recognizing:

“Spiral order” / “clockwise from outside in” → four boundaries + four directions


Core Template: Spiral Traversal

public List<Integer> spiralOrder(int[][] matrix) {
    List<Integer> result = new ArrayList<>();

    int top = 0;
    int bottom = matrix.length - 1;
    int left = 0;
    int right = matrix[0].length - 1;

    while (top <= bottom && left <= right) {

        for (int col = left; col <= right; col++)   // → top row
            result.add(matrix[top][col]);
        top++;

        for (int row = top; row <= bottom; row++)   // ↓ right col
            result.add(matrix[row][right]);
        right--;

        if (top <= bottom) {                        // ← bottom row
            for (int col = right; col >= left; col--)
                result.add(matrix[bottom][col]);
            bottom--;
        }

        if (left <= right) {                        // ↑ left col
            for (int row = bottom; row >= top; row--)
                result.add(matrix[row][left]);
            left++;
        }
    }

    return result;
}
def spiral_order(matrix):
    top, bottom = 0, len(matrix) - 1
    left, right = 0, len(matrix[0]) - 1
    result = []

    while top <= bottom and left <= right:
        for col in range(left, right + 1):      # → top row
            result.append(matrix[top][col])
        top += 1

        for row in range(top, bottom + 1):      # ↓ right col
            result.append(matrix[row][right])
        right -= 1

        if top <= bottom:                       # ← bottom row
            for col in range(right, left - 1, -1):
                result.append(matrix[bottom][col])
            bottom -= 1

        if left <= right:                       # ↑ left col
            for row in range(bottom, top - 1, -1):
                result.append(matrix[row][left])
            left += 1

    return result
vector<int> spiralOrder(vector<vector<int>>& matrix) {
    int top = 0, bottom = matrix.size() - 1;
    int left = 0, right = matrix[0].size() - 1;
    vector<int> result;

    while (top <= bottom && left <= right) {

        for (int col = left; col <= right; col++)   // → top row
            result.push_back(matrix[top][col]);
        top++;

        for (int row = top; row <= bottom; row++)   // ↓ right col
            result.push_back(matrix[row][right]);
        right--;

        if (top <= bottom) {                        // ← bottom row
            for (int col = right; col >= left; col--)
                result.push_back(matrix[bottom][col]);
            bottom--;
        }

        if (left <= right) {                        // ↑ left col
            for (int row = bottom; row >= top; row--)
                result.push_back(matrix[row][left]);
            left++;
        }
    }

    return result;
}
function spiralOrder(matrix) {
  let top = 0,
    bottom = matrix.length - 1,
    left = 0,
    right = matrix[0].length - 1;
  const result = [];

  while (top <= bottom && left <= right) {
    for (let col = left; col <= right; col++)
      result.push(matrix[top][col]); // → top row
    top++;

    for (let row = top; row <= bottom; row++)
      result.push(matrix[row][right]); // ↓ right col
    right--;

    if (top <= bottom) {
      // ← bottom row
      for (let col = right; col >= left; col--)
        result.push(matrix[bottom][col]);
      bottom--;
    }

    if (left <= right) {
      // ↑ left col
      for (let row = bottom; row >= top; row--)
        result.push(matrix[row][left]);
      left++;
    }
  }

  return result;
}

The two if guards before edges 3 and 4 prevent double-visiting when only one row or column remains.


Four variables (top/bottom/left/right) own the current layer. Walk an edge, shrink its boundary.


Variant: Generate Spiral Matrix

Watch [1..9] unwind as 1 2 3 6 9 8 7 4 5 — each edge walked once, boundaries shrinking after each. Press to animate.

Spiral Traversal

Read a matrix in clockwise spiral order using four shrinking boundaries (top, bottom, left, right). Each edge is consumed, then the boundary moves inward.

Matrix: [[1,2,3],[4,5,6],[7,8,9]]. Top row → right column → bottom row (reverse) → left column (reverse), then repeat on the inner layer. The highlighted cells are the edge being consumed; the state chips track the live boundaries (top/bottom/left/right).

GRID VISUALIZER
Steps
1
2
3
4
5
6
7
8
9
Press ▶ to animate, or step through manually.
Variables
keys: ← → space F
Pseudocode

                        1
                        top=0, bottom=rows-1, left=0, right=cols-1
                      
                        2
                        while top <= bottom && left <= right:
                      
                        3
                          left→right along top row; top++
                      
                        4
                          top→bottom along right col; right--
                      
                        5
                          right→left along bottom row; bottom--
                      
                        6
                          bottom→top along left col; left++
                      

Same boundary walk — but write values instead of reading them:

public int[][] generateMatrix(int n) {
    int[][] matrix = new int[n][n];
    int top = 0, bottom = n - 1, left = 0, right = n - 1;
    int value = 1;

    while (top <= bottom && left <= right) {
        for (int col = left; col <= right; col++)
            matrix[top][col] = value++;
        top++;

        for (int row = top; row <= bottom; row++)
            matrix[row][right] = value++;
        right--;

        if (top <= bottom) {
            for (int col = right; col >= left; col--)
                matrix[bottom][col] = value++;
            bottom--;
        }

        if (left <= right) {
            for (int row = bottom; row >= top; row--)
                matrix[row][left] = value++;
            left++;
        }
    }

    return matrix;
}
def generate_matrix(n):
    matrix = [[0] * n for _ in range(n)]
    top, bottom, left, right = 0, n - 1, 0, n - 1
    value = 1

    while top <= bottom and left <= right:
        for col in range(left, right + 1):
            matrix[top][col] = value
            value += 1
        top += 1

        for row in range(top, bottom + 1):
            matrix[row][right] = value
            value += 1
        right -= 1

        if top <= bottom:
            for col in range(right, left - 1, -1):
                matrix[bottom][col] = value
                value += 1
            bottom -= 1

        if left <= right:
            for row in range(bottom, top - 1, -1):
                matrix[row][left] = value
                value += 1
            left += 1

    return matrix
vector<vector<int>> generateMatrix(int n) {
    vector<vector<int>> matrix(n, vector<int>(n));
    int top = 0, bottom = n - 1, left = 0, right = n - 1;
    int value = 1;

    while (top <= bottom && left <= right) {
        for (int col = left; col <= right; col++)
            matrix[top][col] = value++;
        top++;

        for (int row = top; row <= bottom; row++)
            matrix[row][right] = value++;
        right--;

        if (top <= bottom) {
            for (int col = right; col >= left; col--)
                matrix[bottom][col] = value++;
            bottom--;
        }

        if (left <= right) {
            for (int row = bottom; row >= top; row--)
                matrix[row][left] = value++;
            left++;
        }
    }

    return matrix;
}
function generateMatrix(n) {
  const matrix = Array.from({ length: n }, () => Array(n).fill(0));
  let top = 0,
    bottom = n - 1,
    left = 0,
    right = n - 1,
    value = 1;

  while (top <= bottom && left <= right) {
    for (let col = left; col <= right; col++) matrix[top][col] = value++;
    top++;

    for (let row = top; row <= bottom; row++) matrix[row][right] = value++;
    right--;

    if (top <= bottom) {
      for (let col = right; col >= left; col--)
        matrix[bottom][col] = value++;
      bottom--;
    }

    if (left <= right) {
      for (let row = bottom; row >= top; row--)
        matrix[row][left] = value++;
      left++;
    }
  }

  return matrix;
}

Counter-clockwise variant: same skeleton with the direction order rotated (↑ → ↓ ←) or the matrix transposed afterwards.


Common Mistakes

Missing the single-row/single-column guards.

Without if (top <= bottom) / if (left <= right), rectangular matrices get cells visited twice on the last layer.


Shrinking at the wrong time.

Increment top only AFTER walking the top row — shrink-as-you-go keeps each edge’s range correct.


Hardcoding square matrices.

m × n works fine with four independent boundaries — don’t assume n × n.


Complexity

OperationTimeSpace
TraverseO(n·m)O(1) extra
GenerateO(n²)O(n²) output

My Private Notes

Notes are auto-saved locally to this device.