Placement Prep

Spiral Matrix Printing: Print a 2D Matrix in Spiral Order

Print a 2D matrix in spiral order with the boundary-shrink approach. Python and Java solutions with traced examples for 3×3, 3×4, and edge cases.

By FACE Prep Team 5 min read
dsa matrix arrays spiral-traversal two-pointers interview-prep algorithm placement-prep

Spiral order traversal visits every element in a 2D matrix by walking the outer ring first, then the next ring inward, repeating until no elements remain. It is one of the cleaner matrix problems to understand once you see the boundary-shrink pattern, and it shows up in placement coding rounds across service-track and product-track companies.

What Is Spiral Order Traversal?

Given an m x n matrix, spiral order means reading elements in this sequence:

  • Left to right across the top row
  • Top to bottom down the rightmost column
  • Right to left across the bottom row
  • Bottom to top up the leftmost column

Then repeat for the next inner ring, and so on.

For the 3 x 3 matrix [[1,2,3],[4,5,6],[7,8,9]]:

1  2  3
4  5  6
7  8  9

The spiral output is [1, 2, 3, 6, 9, 8, 7, 4, 5]. Outer ring first (1 to 2 to 3 to 6 to 9 to 8 to 7 to 4), then the single remaining element (5).

This is LeetCode 54 in its canonical form. The same problem appears as a coding question in placement rounds at companies including PayPal and Flipkart, based on FACE Prep’s placement records. For similar array-manipulation problems that appear alongside matrix questions in technical rounds, see program to find all symmetric pairs in an array.

The Boundary-Shrink Approach

Track four integer pointers that represent the current active boundary of the matrix:

PointerInitial valueMeaning
top0Index of the topmost unprocessed row
bottomm - 1Index of the bottommost unprocessed row
left0Index of the leftmost unprocessed column
rightn - 1Index of the rightmost unprocessed column

The loop runs while top <= bottom and left <= right. Each iteration performs four directional sweeps and shrinks the corresponding boundary by one.

Step-by-step logic

  • Left to right along top row: collect matrix[top][left] through matrix[top][right]. Increment top.
  • Top to bottom along right column: collect matrix[top][right] through matrix[bottom][right]. Decrement right.
  • Right to left along bottom row (guard: top <= bottom): collect matrix[bottom][right] through matrix[bottom][left]. Decrement bottom.
  • Bottom to top along left column (guard: left <= right): collect matrix[bottom][left] through matrix[top][left]. Increment left.

The two guards prevent double-collection on single-row or single-column remainders. Without the guard before the right-to-left sweep, a single remaining row would be read left-to-right and then again right-to-left, duplicating every element.

Worked Examples

3 x 3 matrix

Input:  [[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]]

Trace with top=0, bottom=2, left=0, right=2:

  • Left to right row 0: 1, 2, 3 → top becomes 1
  • Top to bottom col 2: 6, 9 → right becomes 1
  • Right to left row 2 (guard passes): 8, 7 → bottom becomes 1
  • Bottom to top col 0 (guard passes): 4 → left becomes 1
  • Left to right row 1: 5 → top becomes 2
  • Loop exits (top=2 > bottom=1)

Output: [1, 2, 3, 6, 9, 8, 7, 4, 5]

3 x 4 matrix

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

Trace with top=0, bottom=2, left=0, right=3:

  • Left to right row 0: 1, 2, 3, 4 → top becomes 1
  • Top to bottom col 3: 8, 12 → right becomes 2
  • Right to left row 2: 11, 10, 9 → bottom becomes 1
  • Bottom to top col 0: 5 → left becomes 1
  • Left to right row 1: 6, 7 → top becomes 2; loop exits

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

1 x 5 matrix (single-row edge case)

Input:  [[1, 2, 3, 4, 5]]

top=0, bottom=0, left=0, right=4:

  • Left to right row 0: 1, 2, 3, 4, 5 → top becomes 1
  • Top to bottom col 4: range is empty (top > bottom)
  • Guard top <= bottom fails, right-to-left sweep skipped
  • Guard left <= right passes, but bottom-to-top col 0 range is also empty
  • Loop exits

Output: [1, 2, 3, 4, 5] (no duplicates)

4 x 1 matrix (single-column edge case)

Input:  [[1], [2], [3], [4]]

top=0, bottom=3, left=0, right=0:

  • Left to right row 0: 1 → top becomes 1
  • Top to bottom col 0: 2, 3, 4 → right becomes -1
  • Guard left <= right fails (left=0, right=-1), bottom-to-top skipped
  • Loop exits

Output: [1, 2, 3, 4] (clean single pass)

Python and Java Implementations

Python

def spiral_order(matrix):
    result = []
    if not matrix or not matrix[0]:
        return result

    top, bottom = 0, len(matrix) - 1
    left, right = 0, len(matrix[0]) - 1

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

        # Top to bottom along right column
        for row in range(top, bottom + 1):
            result.append(matrix[row][right])
        right -= 1

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

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

    return result

Java

import java.util.ArrayList;
import java.util.List;

public List<Integer> spiralOrder(int[][] matrix) {
    List<Integer> result = new ArrayList<>();
    if (matrix == null || matrix.length == 0) return result;

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

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

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

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

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

Complexity and Placement Context

Time and space breakdown:

MetricValueReason
Time complexityO(m x n)Every element is visited exactly once
Space complexityO(1) extraOnly four integer pointers; output list not counted
In-placeYes (read-only)Matrix is not modified

The O(1) extra space is what makes boundary-shrink cleaner than recursive approaches or layer-copying approaches. For a deeper look at how space complexity is classified across algorithm types, see space complexity of algorithms with examples.

Spiral matrix appears as a standalone coding question and as a sub-problem inside larger matrix problems. PayPal’s placement process has included this problem in online assessment rounds, based on FACE Prep’s placement records. The GeeksforGeeks spiral matrix reference lists additional company attributions if you want to cross-check which rounds use it.

The boundary-shrink pattern here (consume the outer layer, shrink all four pointers inward, repeat) is the same structural instinct you use when building LLM pipelines that process long documents in sliding chunks. If you have the spiral pattern solid and want to apply that layer-by-layer thinking to building with LLMs, TinkerLLM is a ₹299 entry point to that skill set.

Primary sources

Frequently asked questions

What is the time complexity of spiral matrix printing?

O(m x n), because every element is visited exactly once during the traversal. No element is skipped or revisited.

Why are the inner guards needed inside the loop?

The guards before the right-to-left sweep and before the bottom-to-top sweep prevent a single-row or single-column remainder from being traversed twice, which would produce duplicate elements in the output.

How does the 1xN edge case work with boundary shrinking?

For a 1-row matrix, top equals bottom from the start. The left-to-right sweep collects all elements and increments top past bottom. The top-to-bottom sweep and right-to-left sweep produce nothing, and the loop exits cleanly.

Is this the same as LeetCode 54 Spiral Matrix?

Yes. LeetCode problem 54 is the standard statement of this problem. The boundary-shrink approach described here passes all LeetCode 54 test cases, including the 1x1, 1xN, Nx1, and empty-matrix edge cases.

What is the difference between spiral-order printing and in-place spiral rotation?

Spiral-order printing reads elements in spiral sequence without modifying the matrix, with O(1) extra space. In-place spiral rotation rearranges the matrix so the outer ring physically shifts. They are different problems with different constraints.

Build AI projects

A self-paced playground for building with LLMs.

TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.

Try TinkerLLM (₹299 launch)
Free AI Roadmap PDF