Spiral Matrix
Problem Statement
Section titled “Problem Statement”Given an m x n matrix, return all elements of the matrix in spiral order (clockwise, starting from the top-left corner).
A spiral order means: move right along the top row, then down along the right column, then left along the bottom row, then up along the left column, and repeat for inner layers.
Examples
Section titled “Examples”| Matrix | Output | Explanation |
|---|---|---|
[[1,2,3],[4,5,6],[7,8,9]] | [1,2,3,6,9,8,7,4,5] | Right → Down → Left → Up (spiral inward) |
[[1,2,3,4],[5,6,7,8],[9,10,11,12]] | [1,2,3,4,8,12,11,10,9,5,6,7] | Same spiral pattern on a 3x4 matrix |
[[1]] | [1] | Single element returns itself |
[[1,2],[3,4]] | [1,2,4,3] | 2x2 matrix: right, down, left |
Constraints
Section titled “Constraints”m == matrix.lengthn == matrix[i].length1 <= m, n <= 10-100 <= matrix[i][j] <= 100
Real-World Applications
Section titled “Real-World Applications”Complexity Comparison
Section titled “Complexity Comparison”| Approach | Time | Space | Best When |
|---|---|---|---|
| Simulation with Boundaries | O(m * n) | O(1)* | Easiest to understand and implement |
| Layer-by-Layer | O(m * n) | O(1)* | Conceptually cleaner, similar performance |
* Excluding the output list.
Which approach should you learn first?
Section titled “Which approach should you learn first?”- Pick Simulation with Boundaries if you prefer explicit control of four directions and shrinking edges.
- Pick Layer-by-Layer if you prefer thinking in terms of concentric rectangles or “peeling” the matrix.
Both have identical time and space complexity — choose based on mental model preference.
Approach 1: Simulation with Boundaries (Recommended)
Section titled “Approach 1: Simulation with Boundaries (Recommended)”Maintain four boundaries: top, bottom, left, and right. Traverse in four directions (right, down, left, up), shrinking the appropriate boundary after each direction. Repeat until all cells are visited.
This approach is the most direct and easiest to visualize—you literally simulate the spiral motion.
Step-by-step Example
Section titled “Step-by-step Example”Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Initial boundaries: top=0, bottom=2, left=0, right=2
| Step | Direction | Cells Added | Boundary Update | Description |
|---|---|---|---|---|
| 1 | Right | 1, 2, 3 | top=1 | Traverse row 0 left-to-right |
| 2 | Down | 6, 9 | right=1 | Traverse column 2 top-to-bottom |
| 3 | Left | 8, 7 | bottom=1 | Traverse row 2 right-to-left |
| 4 | Up | 4 | left=1 | Traverse column 0 bottom-to-top |
| 5 | Right | 5 | top=1 | Center element (last layer) |
Final Output: [1, 2, 3, 6, 9, 8, 7, 4, 5]
Animated walkthrough
Watch the boundaries (top, bottom, left, right) shrink as you spiral inward. Each direction adds cells to the result and updates a boundary.
Pseudocode
Section titled “Pseudocode”function spiralMatrixSimulation(matrix): if matrix is empty: return []
result = [] top = 0, bottom = rows - 1 left = 0, right = cols - 1
while top <= bottom and left <= right: // Traverse right for col in [left, right]: result.append(matrix[top][col]) top += 1
// Traverse down for row in [top, bottom]: result.append(matrix[row][right]) right -= 1
// Traverse left (if row remains) if top <= bottom: for col in [right, left] reversed: result.append(matrix[bottom][col]) bottom -= 1
// Traverse up (if column remains) if left <= right: for row in [bottom, top] reversed: result.append(matrix[row][left]) left += 1
return resultSolution Code
Section titled “Solution Code”from typing import List
def spiral_matrix_simulation(matrix: List[List[int]]) -> List[int]: """ Traverse the matrix in spiral order using boundary tracking.
Time Complexity: O(m * n) where m is rows and n is columns Space Complexity: O(1) excluding the result list """ 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: # Traverse right for col in range(left, right + 1): result.append(matrix[top][col]) top += 1
# Traverse down for row in range(top, bottom + 1): result.append(matrix[row][right]) right -= 1
# Traverse left (if there's a row remaining) if top <= bottom: for col in range(right, left - 1, -1): result.append(matrix[bottom][col]) bottom -= 1
# Traverse up (if there's a column remaining) if left <= right: for row in range(bottom, top - 1, -1): result.append(matrix[row][left]) left += 1
return result
# Test casesprint(spiral_matrix_simulation([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) # [1, 2, 3, 6, 9, 8, 7, 4, 5]print(spiral_matrix_simulation([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])) # [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]#include <iostream>#include <vector>
std::vector<int> spiralMatrixSimulation(std::vector<std::vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) { return {}; }
std::vector<int> result; int top = 0, bottom = matrix.size() - 1; int left = 0, right = matrix[0].size() - 1;
while (top <= bottom && left <= right) { // Traverse right for (int col = left; col <= right; col++) { result.push_back(matrix[top][col]); } top++;
// Traverse down for (int row = top; row <= bottom; row++) { result.push_back(matrix[row][right]); } right--;
// Traverse left (if there's a row remaining) if (top <= bottom) { for (int col = right; col >= left; col--) { result.push_back(matrix[bottom][col]); } bottom--; }
// Traverse up (if there's a column remaining) if (left <= right) { for (int row = bottom; row >= top; row--) { result.push_back(matrix[row][left]); } left++; } }
return result;}
int main() { std::vector<std::vector<int>> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; std::vector<int> result = spiralMatrixSimulation(matrix); for (int num : result) { std::cout << num << " "; } std::cout << std::endl; return 0;}import java.util.ArrayList;import java.util.Arrays;import java.util.List;
public class Main { public static List<Integer> spiralMatrixSimulation(int[][] matrix) { List<Integer> result = new ArrayList<>(); if (matrix.length == 0 || matrix[0].length == 0) { return result; }
int top = 0, bottom = matrix.length - 1; int left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) { // Traverse right for (int col = left; col <= right; col++) { result.add(matrix[top][col]); } top++;
// Traverse down for (int row = top; row <= bottom; row++) { result.add(matrix[row][right]); } right--;
// Traverse left (if there's a row remaining) if (top <= bottom) { for (int col = right; col >= left; col--) { result.add(matrix[bottom][col]); } bottom--; }
// Traverse up (if there's a column remaining) 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}}; List<Integer> result = spiralMatrixSimulation(matrix); System.out.println(result); }}function spiralMatrixSimulation(matrix) { if (!matrix || matrix.length === 0 || matrix[0].length === 0) { return []; }
const result = []; let top = 0, bottom = matrix.length - 1; let left = 0, right = matrix[0].length - 1;
while (top <= bottom && left <= right) { // Traverse right for (let col = left; col <= right; col++) { result.push(matrix[top][col]); } top++;
// Traverse down for (let row = top; row <= bottom; row++) { result.push(matrix[row][right]); } right--;
// Traverse left (if there's a row remaining) if (top <= bottom) { for (let col = right; col >= left; col--) { result.push(matrix[bottom][col]); } bottom--; }
// Traverse up (if there's a column remaining) if (left <= right) { for (let row = bottom; row >= top; row--) { result.push(matrix[row][left]); } left++; } }
return result;}
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];const result = spiralMatrixSimulation(matrix);console.log(result);fn spiral_matrix_simulation(matrix: &[Vec<i32>]) -> Vec<i32> { if matrix.is_empty() || matrix[0].is_empty() { return vec![]; }
let mut result = vec![]; let mut top = 0; let mut bottom = matrix.len() as i32 - 1; let mut left = 0; let mut right = matrix[0].len() as i32 - 1;
while top <= bottom && left <= right { // Traverse right for col in left..=right { result.push(matrix[top as usize][col as usize]); } top += 1;
// Traverse down for row in top..=bottom { result.push(matrix[row as usize][right as usize]); } right -= 1;
// Traverse left (if there's a row remaining) if top <= bottom { for col in (left..=right).rev() { result.push(matrix[bottom as usize][col as usize]); } bottom -= 1; }
// Traverse up (if there's a column remaining) if left <= right { for row in (top..=bottom).rev() { result.push(matrix[row as usize][left as usize]); } left += 1; } }
result}
fn main() { let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]; let result = spiral_matrix_simulation(&matrix); println!("{:?}", result);}package main
import "fmt"
func spiralMatrixSimulation(matrix [][]int) []int { if len(matrix) == 0 || len(matrix[0]) == 0 { return []int{} }
result := []int{} top, bottom := 0, len(matrix)-1 left, right := 0, len(matrix[0])-1
for top <= bottom && left <= right { // Traverse right for col := left; col <= right; col++ { result = append(result, matrix[top][col]) } top++
// Traverse down for row := top; row <= bottom; row++ { result = append(result, matrix[row][right]) } right--
// Traverse left (if there's a row remaining) if top <= bottom { for col := right; col >= left; col-- { result = append(result, matrix[bottom][col]) } bottom-- }
// Traverse up (if there's a column remaining) if left <= right { for row := bottom; row >= top; row-- { result = append(result, matrix[row][left]) } left++ } }
return result}
func main() { matrix := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} result := spiralMatrixSimulation(matrix) fmt.Println(result)}Approach 2: Layer-by-Layer
Section titled “Approach 2: Layer-by-Layer”Instead of thinking in terms of four directions and shrinking boundaries, think of the matrix as concentric rectangular layers. Process each layer from outside to inside, treating each layer as a rectangle.
This approach is conceptually equivalent to Approach 1 but organizes the logic around layers rather than directions.
Step-by-step Example
Section titled “Step-by-step Example”Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Layers: layer 0 (outer) and layer 1 (inner/center)
| Layer | Elements | Description |
|---|---|---|
| 0 | [1, 2, 3, 6, 9, 8, 7, 4] | Outer rectangle perimeter |
| 1 | [5] | Center element (innermost layer) |
Final Output: [1, 2, 3, 6, 9, 8, 7, 4, 5]
The number of layers is (min(m, n) + 1) / 2. For a 3x3 matrix, that’s (3 + 1) / 2 = 2 layers.
Pseudocode
Section titled “Pseudocode”function spiralMatrixLayer(matrix): if matrix is empty: return []
result = [] m, n = rows, cols layers = (min(m, n) + 1) / 2
for layer in [0, layers): top = layer bottom = m - 1 - layer left = layer right = n - 1 - layer
// Traverse right for col in [left, right]: result.append(matrix[top][col])
// Traverse down for row in [top+1, bottom]: result.append(matrix[row][right])
// Traverse left (if row remains) if top < bottom: for col in [right-1, left] reversed: result.append(matrix[bottom][col])
// Traverse up (if column remains) if left < right: for row in [bottom-1, top+1] reversed: result.append(matrix[row][left])
return resultSolution Code
Section titled “Solution Code”from typing import List
def spiral_matrix_layer(matrix: List[List[int]]) -> List[int]: """ Traverse the matrix in spiral order by peeling off layers.
Time Complexity: O(m * n) where m is rows and n is columns Space Complexity: O(1) excluding the result list """ if not matrix or not matrix[0]: return []
result = [] m, n = len(matrix), len(matrix[0]) layers = (min(m, n) + 1) // 2
for layer in range(layers): top = layer bottom = m - 1 - layer left = layer right = n - 1 - layer
# Traverse right for col in range(left, right + 1): result.append(matrix[top][col])
# Traverse down for row in range(top + 1, bottom + 1): result.append(matrix[row][right])
# Traverse left (if there's a row remaining) if top < bottom: for col in range(right - 1, left - 1, -1): result.append(matrix[bottom][col])
# Traverse up (if there's a column remaining) if left < right: for row in range(bottom - 1, top, -1): result.append(matrix[row][left])
return result
# Test casesprint(spiral_matrix_layer([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) # [1, 2, 3, 6, 9, 8, 7, 4, 5]print(spiral_matrix_layer([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])) # [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7]#include <iostream>#include <vector>#include <algorithm>
std::vector<int> spiralMatrixLayer(std::vector<std::vector<int>>& matrix) { if (matrix.empty() || matrix[0].empty()) { return {}; }
std::vector<int> result; int m = matrix.size(); int n = matrix[0].size(); int layers = (std::min(m, n) + 1) / 2;
for (int layer = 0; layer < layers; layer++) { int top = layer; int bottom = m - 1 - layer; int left = layer; int right = n - 1 - layer;
// Traverse right for (int col = left; col <= right; col++) { result.push_back(matrix[top][col]); }
// Traverse down for (int row = top + 1; row <= bottom; row++) { result.push_back(matrix[row][right]); }
// Traverse left (if there's a row remaining) if (top < bottom) { for (int col = right - 1; col >= left; col--) { result.push_back(matrix[bottom][col]); } }
// Traverse up (if there's a column remaining) if (left < right) { for (int row = bottom - 1; row > top; row--) { result.push_back(matrix[row][left]); } } }
return result;}
int main() { std::vector<std::vector<int>> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; std::vector<int> result = spiralMatrixLayer(matrix); for (int num : result) { std::cout << num << " "; } std::cout << std::endl; return 0;}import java.util.ArrayList;import java.util.List;
public class Main { public static List<Integer> spiralMatrixLayer(int[][] matrix) { List<Integer> result = new ArrayList<>(); if (matrix.length == 0 || matrix[0].length == 0) { return result; }
int m = matrix.length; int n = matrix[0].length; int layers = (Math.min(m, n) + 1) / 2;
for (int layer = 0; layer < layers; layer++) { int top = layer; int bottom = m - 1 - layer; int left = layer; int right = n - 1 - layer;
// Traverse right for (int col = left; col <= right; col++) { result.add(matrix[top][col]); }
// Traverse down for (int row = top + 1; row <= bottom; row++) { result.add(matrix[row][right]); }
// Traverse left (if there's a row remaining) if (top < bottom) { for (int col = right - 1; col >= left; col--) { result.add(matrix[bottom][col]); } }
// Traverse up (if there's a column remaining) if (left < right) { for (int row = bottom - 1; row > top; row--) { result.add(matrix[row][left]); } } }
return result; }
public static void main(String[] args) { int[][] matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; List<Integer> result = spiralMatrixLayer(matrix); System.out.println(result); }}function spiralMatrixLayer(matrix) { if (!matrix || matrix.length === 0 || matrix[0].length === 0) { return []; }
const result = []; const m = matrix.length; const n = matrix[0].length; const layers = Math.floor((Math.min(m, n) + 1) / 2);
for (let layer = 0; layer < layers; layer++) { const top = layer; const bottom = m - 1 - layer; const left = layer; const right = n - 1 - layer;
// Traverse right for (let col = left; col <= right; col++) { result.push(matrix[top][col]); }
// Traverse down for (let row = top + 1; row <= bottom; row++) { result.push(matrix[row][right]); }
// Traverse left (if there's a row remaining) if (top < bottom) { for (let col = right - 1; col >= left; col--) { result.push(matrix[bottom][col]); } }
// Traverse up (if there's a column remaining) if (left < right) { for (let row = bottom - 1; row > top; row--) { result.push(matrix[row][left]); } } }
return result;}
const matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];const result = spiralMatrixLayer(matrix);console.log(result);fn spiral_matrix_layer(matrix: &[Vec<i32>]) -> Vec<i32> { if matrix.is_empty() || matrix[0].is_empty() { return vec![]; }
let mut result = vec![]; let m = matrix.len() as i32; let n = matrix[0].len() as i32; let layers = (m.min(n) + 1) / 2;
for layer in 0..layers { let top = layer; let bottom = m - 1 - layer; let left = layer; let right = n - 1 - layer;
// Traverse right for col in left..=right { result.push(matrix[top as usize][col as usize]); }
// Traverse down for row in (top + 1)..=bottom { result.push(matrix[row as usize][right as usize]); }
// Traverse left (if there's a row remaining) if top < bottom { for col in (left..right).rev() { result.push(matrix[bottom as usize][col as usize]); } }
// Traverse up (if there's a column remaining) if left < right { for row in ((top + 1)..bottom).rev() { result.push(matrix[row as usize][left as usize]); } } }
result}
fn main() { let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]; let result = spiral_matrix_layer(&matrix); println!("{:?}", result);}package main
import "fmt"
func spiralMatrixLayer(matrix [][]int) []int { if len(matrix) == 0 || len(matrix[0]) == 0 { return []int{} }
result := []int{} m, n := len(matrix), len(matrix[0]) layers := (min(m, n) + 1) / 2
for layer := 0; layer < layers; layer++ { top := layer bottom := m - 1 - layer left := layer right := n - 1 - layer
// Traverse right for col := left; col <= right; col++ { result = append(result, matrix[top][col]) }
// Traverse down for row := top + 1; row <= bottom; row++ { result = append(result, matrix[row][right]) }
// Traverse left (if there's a row remaining) if top < bottom { for col := right - 1; col >= left; col-- { result = append(result, matrix[bottom][col]) } }
// Traverse up (if there's a column remaining) if left < right { for row := bottom - 1; row > top; row-- { result = append(result, matrix[row][left]) } } }
return result}
func min(a, b int) int { if a < b { return a } return b}
func main() { matrix := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} result := spiralMatrixLayer(matrix) fmt.Println(result)}Approach 3: Space-Optimized Variant
Section titled “Approach 3: Space-Optimized Variant”A third approach demonstrating an alternative technique for solving this problem. This implementation optimizes either time or space complexity compared to the previous approaches.
Pseudocode
Section titled “Pseudocode”function approach3(): // Implementation approach goes hereSolution Code
Section titled “Solution Code”"""Solution for Spiral Matrix"""
def solve(): """Implementation for approach 3 of Spiral Matrix""" pass
if __name__ == "__main__": print("Solution ready")#include <bits/stdc++.h>using namespace std;
// Solution for Spiral Matrix// Approach 3: Implementation
int main() {{ // Main implementation goes here return 0;}}/** * Solution for Spiral Matrix * Approach 3 */public class SpiralMatrixSpaceOptimized {{
public static void main(String[] args) {{ // Implementation goes here }}}}/** * Solution for Spiral Matrix * Approach 3 */
function solve() {{ // Implementation goes here}}
module.exports = solve;/// Solution for Spiral Matrix/// Approach 3
fn main() {{ println!("Solution implementation");}}package main
import "fmt"
// Solution for Spiral Matrix// Approach 3
func main() {{ fmt.Println("Solution implementation")}}