@Note: This is categorized as โDifficultโ because it is a complex 2D array traversal index problem with multiple indices that can easily lead to IndexOutOfBoundsException bugs.
Category: Difficult | Concepts used: Boundary tracking, 2D array traversal
Problem Statement
Given a 2D matrix, print all its elements in spiral order (starting from the top-left, going right, then down, then left, then up, spiraling inward).
Input :
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Output: [1, 2, 3, 6, 9, 8, 7, 4, 5]
Examples (with edge scenarios)
| # | Input Matrix | Output | Why |
|---|---|---|---|
| 1 | 3x3 square matrix (above) | [1,2,3,6,9,8,7,4,5] | Standard spiral |
| 2 | 1x1 matrix [[5]] | [5] | Single element โ trivial spiral |
| 3 | 1xN matrix [[1,2,3,4]] (single row) | [1,2,3,4] | No โdownโ or โupโ movement needed, just left-to-right |
| 4 | Nx1 matrix (single column) | Top to bottom, straight down | No โrightโ or โleftโ movement needed |
| 5 | Non-square (rectangular) matrix, e.g., 2x3 | Still works, just uneven spiral shape | Must handle rows โ columns correctly |
Common Fresher Mistake
Mistake What happens Fix Not updating boundary variables correctly after each direction Elements get printed twice, or missed entirely, or IndexOutOfBoundsExceptionCarefully shrink the boundaries ( top++,bottom--,left++,right--) after completing each of the 4 directional sweepsNot checking boundary validity before the last โupโ and โleftโ sweeps in a partially-completed final ring For single-row or single-column matrices, printing the same row/column twice Add boundary condition checks ( top <= bottom,left <= right) before each directional sweep
Before You Code: Clarify the Contract
Before choosing an algorithm, confirm whether the matrix may be empty, whether every row has the same length, and whether traversal may modify the matrix. The solution below assumes a rectangular matrix and returns values without changing the input.
Analogy: Mowing the Lawn Inward
Imagine you are a lawnmower operator mowing a square field, and you want to mow the grass in a spiral pattern starting from the outer boundary and working inward:
- You have four fence lines marking your boundaries:
top(0),bottom(2),left(0), andright(2). - Mowing Loop:
- Drive East: You mow along the
topboundary fromlefttoright. Once done, you move thetopfence down (top++) since that row is completely cleared. - Drive South: You mow down the
rightboundary fromtoptobottom. Once done, you move therightfence left (right--). - Drive West: If you still have rows left to mow (
top <= bottom), you mow along thebottomboundary fromrighttoleft. Once done, you move thebottomfence up (bottom--). - Drive North: If you still have columns left to mow (
left <= right), you mow up theleftboundary frombottomtotop. Once done, you move theleftfence right (left++).
- Drive East: You mow along the
- You repeat this circular route. Each time, your yard shrinks, until the fences meet and there is no grass left to mow!
Solution 1 โ Boundary Tracking (Four Direction Pointers)
Intuition
Picture the matrix as having four shrinking โwallsโ: top, bottom, left, right. Traverse along each wall in order โ right across the top row, down the right column, left across the bottom row, up the left column โ then shrink the corresponding boundary inward after each sweep (since that outer layer is now fully visited). Repeat this shrinking process until the boundaries cross, meaning every element has been visited.
import java.util.ArrayList;
import java.util.List;
public class SpiralMatrix {
public static List<Integer> spiralOrder(int[][] matrix) {
List<Integer> result = new ArrayList<>();
if (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) {
// 1. Traverse top row, left to right
for (int col = left; col <= right; col++) {
result.add(matrix[top][col]);
}
top++; // top row done, shrink boundary
// 2. Traverse right column, top to bottom
for (int row = top; row <= bottom; row++) {
result.add(matrix[row][right]);
}
right--; // right column done, shrink boundary
// 3. Traverse bottom row, right to left (only if a row remains)
if (top <= bottom) {
for (int col = right; col >= left; col--) {
result.add(matrix[bottom][col]);
}
bottom--;
}
// 4. Traverse left column, bottom to top (only if a column remains)
if (left <= right) {
for (int row = bottom; row >= top; row--) {
result.add(matrix[row][left]);
}
left++;
}
}
return result;
}
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println(spiralOrder(matrix)); // [1, 2, 3, 6, 9, 8, 7, 4, 5]
int[][] singleRow = {{1, 2, 3, 4}};
System.out.println(spiralOrder(singleRow)); // [1, 2, 3, 4]
}
}
Output:
[1, 2, 3, 6, 9, 8, 7, 4, 5]
[1, 2, 3, 4]
Dry Run (3x3 matrix: [[1,2,3],[4,5,6],[7,8,9]])
top=0, bottom=2, left=0, right=2
Loop iteration 1:
Step 1 (top row, left->right): add 1,2,3 -> result=[1,2,3] -> top=1
Step 2 (right col, top->bottom): add 6,9 -> result=[1,2,3,6,9] -> right=1
Step 3 (bottom row, right->left) [top<=bottom, 1<=2 true]: add 8,7 -> result=[1,2,3,6,9,8,7] -> bottom=1
Step 4 (left col, bottom->top) [left<=right, 0<=1 true]: add 4 -> result=[1,2,3,6,9,8,7,4] -> left=1
Loop check: top=1<=bottom=1 AND left=1<=right=1 -> continue
Loop iteration 2:
Step 1 (top row=1, left=1 to right=1): add matrix[1][1]=5 -> result=[...,5] -> top=2
Step 2 (right col, top=2 to bottom=1): loop doesn't execute (2>1) -> right=0
Step 3: top<=bottom? 2<=1 false -> skip
Step 4: left<=right? 1<=0 false -> skip
Loop check: top=2<=bottom=1? false -> loop ends
Final: [1,2,3,6,9,8,7,4,5]
Interviewerโs take
This is the standard, expected solution for spiral matrix traversal โ the boundary-shrinking technique (top/bottom/left/right pointers) is the well-known, correct approach. The tricky part (and what separates a working solution from a buggy one) is the conditional checks before steps 3 and 4 (if (top <= bottom) and if (left <= right)) โ without these, single-row or single-column matrices get elements printed twice.
Follow-up questions you might get:
- โWhy are the checks before steps 3 and 4 necessary, but not before steps 1 and 2?โ โ By the time we reach steps 3 and 4, the boundaries may have already crossed (e.g., after processing a single remaining row in step 1,
topmight now exceedbottom) โ without checking, step 3 would incorrectly re-print the same row that step 1 just handled. - โWhatโs the time and space complexity?โ โ O(rows ร cols) time (every element visited exactly once), O(rows ร cols) space for the result list (or O(1) extra if just printing without storing).
- โHow would you handle an empty matrix, or a matrix with empty rows?โ โ Explicitly check
matrix.length == 0(and potentiallymatrix[0].length == 0) at the start and return an empty result immediately.
๐ Visual Flowchart
graph TD
Start["Input Matrix"] --> Init["top=0, bottom=rows-1<br>left=0, right=cols-1"]
Init --> Loop{"top <= bottom AND left <= right?"}
Loop -->|Yes| Step1["1. Traverse top row (col: left to right)<br>top++"]
Step1 --> Step2["2. Traverse right column (row: top to bottom)<br>right--"]
Step2 --> Guard3{"top <= bottom?"}
Guard3 -->|Yes| Step3["3. Traverse bottom row (col: right to left)<br>bottom--"]
Guard3 -->|No| Guard4
Step3 --> Guard4{"left <= right?"}
Guard4 -->|Yes| Step4["4. Traverse left column (row: bottom to top)<br>left++"]
Guard4 -->|No| Loop
Step4 --> Loop
Loop -->|No| End["Return result List"]
Final Verdict โ Which Solution Should You Give?
- Solution 1 (boundary tracking) is the standard, essentially only reasonable approach for this classic problem โ the key skill being tested is careful boundary management and dry-running through edge cases (single row, single column) to make sure the conditional guards are correctly placed.
- Walking through a non-square example (like a
2x4matrix) during the interview is a great way to demonstrate the boundary logic holds up beyond the โniceโ square case.
Quick Recap
| Approach | Time | Space | Interview Signal |
|---|---|---|---|
| Boundary tracking (4 pointers) | O(rows ร cols) | O(rows ร cols) for result | Standard โ careful edge-case handling is the key skill |
- Author
- TechByteByByte Editorial Team
- Reviewed by
- TechByteByByte Admin
- Published
- Last reviewed