# The Spiral Harvest

> The snail reads the grid in its own special order.

Canonical URL: <https://datadriven.io/problems/the_spiral_harvest>

Domain: Python · Difficulty: medium · Seniority: L4

## Problem

Given a 2D matrix, return all elements in spiral order starting top-left, going clockwise (right, down, left, up), layer by layer.

## Worked solution and explanation

### Why this problem exists in real interviews

This tests **boundary tracking** and **direction cycling** in a 2D matrix. Spiral traversal requires careful management of four boundaries (top, bottom, left, right) and is a common probe for attention to detail in index manipulation.

---

### Break down the requirements

#### Step 1: Initialize four boundary pointers

Set `top = 0`, `bottom = rows - 1`, `left = 0`, `right = cols - 1`. These shrink inward as layers are consumed.

#### Step 2: Traverse right, then down, then left, then up

After completing each direction, shrink the corresponding boundary inward by one.

#### Step 3: Stop when boundaries cross

The loop ends when `top > bottom` or `left > right`.

---

### The solution

**Four-boundary shrinking traversal**

```python
def spiral_order(matrix: list) -> list:
    if not matrix or not matrix[0]:
        return []
    result = []
    top = 0
    bottom = len(matrix) - 1
    left = 0
    right = len(matrix[0]) - 1
    while top <= bottom and left <= right:
        for col in range(left, right + 1):
            result.append(matrix[top][col])
        top += 1
        for row in range(top, bottom + 1):
            result.append(matrix[row][right])
        right -= 1
        if top <= bottom:
            for col in range(right, left - 1, -1):
                result.append(matrix[bottom][col])
            bottom -= 1
        if left <= right:
            for row in range(bottom, top - 1, -1):
                result.append(matrix[row][left])
            left += 1
    return result
```

> **Time and Space Complexity**
>
> **Time:** O(m * n) where m and n are the matrix dimensions. Each element is visited exactly once.
> 
> **Space:** O(1) beyond the result list. The boundary pointers use constant space.

> **Interviewers Watch For**
>
> The conditional checks `if top <= bottom` and `if left <= right` before the left and up traversals prevent double-counting in non-square matrices. Missing these checks is the most common bug.

> **Common Pitfall**
>
> Off-by-one errors in the range endpoints. Using `range(right, left - 1, -1)` ensures the leftmost column is included when traversing leftward.

---

## Common follow-up questions

- How would you generate a spiral matrix instead of reading one? _(Tests filling an empty matrix with values 1 to m*n in spiral order.)_
- What if the matrix is 1xN or Nx1? _(Tests that single-row and single-column edge cases are handled by the boundary checks.)_
- How would you traverse in counter-clockwise spiral order? _(Tests reversing the direction cycle: down, right, up, left.)_

## Related

- [All practice problems](https://datadriven.io/problems)
- [Mock interview mode](https://datadriven.io/interview/the_spiral_harvest)
- [Python Interview Questions](https://datadriven.io/python-interview-questions)
- [Data Engineering Interview Prep Guide](https://datadriven.io/data-engineer-interview-prep)
- [Daily Challenge](https://datadriven.io/daily)

---

Source: DataDriven (https://datadriven.io). 100% free data engineering interview prep. Live code execution against Postgres 16, Python 3.11, and Spark sandboxes. No paywall, no premium tier, no signup gate.