Given an m x n matrix, return all elements of the matrix in spiral order.
Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]
Visual:
1 → 2 → 3
↓
4 5 6
↑ ↓
7 ← 8 ← 9
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]
Visual:
1 → 2 → 3 → 4
↓
5 6 7 8
↑ ↓
9 ← 10← 11← 12
Input: matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
Output: [1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
m == matrix.lengthn == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100This problem uses a boundary-tracking approach with simulation.
Track four boundaries (top, bottom, left, right) and shrink them as you complete each edge!
The spiral follows a pattern: Right → Down → Left → Up, repeating until all elements are visited.
Initialize boundaries:
top = 0 (topmost row)bottom = m - 1 (bottommost row)left = 0 (leftmost column)right = n - 1 (rightmost column)Traverse in spiral order:
left to right along top row, then increment toptop to bottom along right column, then decrement rightright to left along bottom row, then decrement bottombottom to top along left column, then increment leftRepeat while top <= bottom && left <= right
For matrix = [[1,2,3],[4,5,6],[7,8,9]]:
Initial: top=0, bottom=2, left=0, right=2
Result: [1,2,3,6,9,8,7,4,5]
By maintaining boundaries, we:
Time Complexity: O(m × n)
Space Complexity: O(1)
import java.util.*;
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
if (matrix == null || matrix.length == 0) {
return result;
}
int m = matrix.length;
int n = matrix[0].length;
int top = 0, bottom = m - 1;
int left = 0, right = n - 1;
while (top <= bottom && left <= right) {
// Move right along top row
for (int i = left; i <= right; i++) {
result.add(matrix[top][i]);
}
top++;
// Move down along right column
for (int i = top; i <= bottom; i++) {
result.add(matrix[i][right]);
}
right--;
// Move left along bottom row (if still valid)
if (top <= bottom) {
for (int i = right; i >= left; i--) {
result.add(matrix[bottom][i]);
}
bottom--;
}
// Move up along left column (if still valid)
if (left <= right) {
for (int i = bottom; i >= top; i--) {
result.add(matrix[i][left]);
}
left++;
}
}
return result;
}
}
def spiralOrder(matrix: List[List[int]]) -> List[int]:
if not matrix:
return []
m, n = len(matrix), len(matrix[0])
result = []
top, bottom = 0, m - 1
left, right = 0, n - 1
while top <= bottom and left <= right:
# Move right
for i in range(left, right + 1):
result.append(matrix[top][i])
top += 1
# Move down
for i in range(top, bottom + 1):
result.append(matrix[i][right])
right -= 1
# Move left (if still valid)
if top <= bottom:
for i in range(right, left - 1, -1):
result.append(matrix[bottom][i])
bottom -= 1
# Move up (if still valid)
if left <= right:
for i in range(bottom, top - 1, -1):
result.append(matrix[i][left])
left += 1
return result
Input: [[1,2,3,4]]
Output: [1,2,3,4]
Just move right, no down/left/up needed.
Input: [[1],[2],[3],[4]]
Output: [1,2,3,4]
Move right (single element), then down.
Input: [[7]]
Output: [7]
Input: [[1,2,3],[4,5,6]]
Output: [1,2,3,6,5,4]
Works perfectly with boundary tracking!
This problem demonstrates:
top <= bottom before moving leftleft <= right before moving upQ: How would you generate a spiral matrix instead of traversing one?
Q: What if you start from the center and spiral outward?
Q: Can you do it recursively?
Q: How to handle very large matrices?
| Approach | Time | Space | Notes | |----------|------|-------|-------| | Boundary Tracking | O(m×n) | O(1) | Optimal, most common | | Visited Array | O(m×n) | O(m×n) | Works but uses extra space | | Recursive | O(m×n) | O(min(m,n)) | Call stack depth |
Recommendation: Boundary tracking is the standard and most efficient approach.
For a 4×4 matrix, the spiral creates concentric rectangles:
Layer 0 (outer):
* * * *
* *
* *
* * * *
Layer 1 (inner):
* *
* *
Each layer is processed clockwise: Right → Down → Left → Up.
top <= bottom && left <= right ensures we stop when boundaries cross