54. Spiral Matrix
Introduction
Today, we’re diving into a classic matrix problem: spiral matrix traversal. Given a 2D matrix, our goal is to extract all its elements in a spiral path, starting from the top-left corner and moving clockwise. Check the leetcode problem here
Problem Statement
Given an m x n matrix, return all elements of the matrix in spiral order.
Example 1:
1
2
3
4
5
Input: matrix = [[1,2,3],
[4,5,6],
[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]
Example 2:
1
2
3
4
5
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]
Constraints:
1
2
3
4
m == matrix.length
n == matrix[i].length
1 <= m, n <= 10
-100 <= matrix[i][j] <= 100
Notice the pattern? We traverse right, then down, then left, then up, and repeat this process inwards until we’ve visited all elements.
Python Solution
Here’s an efficient Python function to achieve spiral matrix traversal:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def spiral_matrix(matrix):
"""
Traverses a matrix in spiral order and returns a list of elements.
Args:
matrix: A 2D list representing the matrix.
Returns:
A list containing all elements of the matrix in spiral order.
"""
if not matrix:
return []
rows, cols = len(matrix), len(matrix[0])
top, bottom = 0, rows - 1
left, right = 0, cols - 1
spiral_order = []
while top <= bottom and left <= right:
# Traverse right (top row)
for col in range(left, right + 1):
spiral_order.append(matrix[top][col])
top += 1
# Traverse down (right column)
for row in range(top, bottom + 1):
spiral_order.append(matrix[row][right])
right -= 1
if top <= bottom and left <= right: # Check if there are more layers to traverse
# Traverse left (bottom row)
for col in range(right, left - 1, -1):
spiral_order.append(matrix[bottom][col])
bottom -= 1
# Traverse up (left column)
for row in range(bottom, top - 1, -1):
spiral_order.append(matrix[row][left])
left += 1
return spiral_order
Explanation
- Initialization:
- We first handle the edge case of an empty matrix. If the matrix is empty, we return an empty list.
- We get the number of
rows
andcols
of the inputmatrix
. - We define four variables:
top
,bottom
,left
, andright
to keep track of the boundaries of the current layer we are traversing. Initially,top
andleft
are 0 (top-left corner), andbottom
andright
are the indices of the last row and column respectively (bottom-right corner). spiral_order
is initialized as an empty list to store the elements in spiral order.
- Spiral Traversal Loop:
- The
while top <= bottom and left <= right:
loop continues as long as there are layers to traverse within the matrix. This condition ensures that we haven’t crossed over the boundaries while spiraling inwards.
- The
- Traverse Right (Top Row):
for col in range(left, right + 1):
iterates through the columns fromleft
toright
in the currenttop
row.spiral_order.append(matrix[top][col])
adds each element of the top row to ourspiral_order
list.top += 1
moves thetop
boundary down by one row, as the top row is now processed.
- Traverse Down (Right Column):
for row in range(top, bottom + 1):
iterates through the rows from the updatedtop
tobottom
in the currentright
column.spiral_order.append(matrix[row][right])
adds each element of the right column tospiral_order
.right -= 1
moves theright
boundary left by one column, as the right column is now processed.
- Conditional Traversal Left and Up:
if top <= bottom and left <= right:
: This crucial condition checks if there are still rows and columns remaining to be traversed after moving right and down. This is necessary to prevent duplicate traversal in cases of non-square matrices or when we reach the center of the matrix.- Traverse Left (Bottom Row):
for col in range(right, left - 1, -1):
iterates through the columns fromright
toleft
(in reverse order) in the currentbottom
row.spiral_order.append(matrix[bottom][col])
adds each element of the bottom row tospiral_order
.bottom -= 1
moves thebottom
boundary up by one row.
- Traverse Up (Left Column):
for row in range(bottom, top - 1, -1):
iterates through the rows frombottom
totop
(in reverse order) in the currentleft
column.spiral_order.append(matrix[row][left])
adds each element of the left column tospiral_order
.left += 1
moves theleft
boundary right by one column.
- Return Result:
- Finally,
return spiral_order
returns the list containing all elements in spiral order.
- Finally,
Time and Space Complexity
- Time Complexity: O(M * N), where M is the number of rows and N is the number of columns in the matrix. We visit each element of the matrix exactly once.
- Space Complexity: O(1), excluding the space required to store the output list. We are only using a constant amount of extra space for variables like
top
,bottom
,left
,right
, and loop counters. If we consider the output list, the space complexity is O(M * N) to store all the elements in thespiral_order
list.
Conclusion
This Python solution efficiently traverses a matrix in spiral order by systematically shrinking the boundaries of the matrix layer by layer. It’s a clear and concise approach that directly simulates the spiral path. Understanding this algorithm is a valuable step in mastering matrix manipulations and algorithmic thinking.
Feel free to experiment with different matrices and see the spiral traversal in action! Let me know in the comments if you have any questions or other interesting matrix problems you’d like to explore. Happy coding!