題目 #
leetcode 54 - Spiral Matrix (題目說明請點連結)
題目簡述 #
給一個 m×n 的二維矩陣,按照順時針螺旋順序返回所有元素。
螺旋順序:從左上角開始,先向右,再向下,再向左,最後向上,如此循環。
範例 #
Example 1:
Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [1,2,3,6,9,8,7,4,5]二維陣列表示:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]螺旋遍歷順序:
1 → 2 → 3
↓
4 → 5 6
↑ ↓
7 ← 8 ← 9Example 2:
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]二維陣列表示:
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]螺旋遍歷順序:
1 → 2 → 3 → 4
↓
5 → 6 → 7 8
↑ ↓
9 ← 10 ← 11 12解題思路 #
這題要求我們按照順時針螺旋順序遍歷矩陣。我們可以使用邊界收縮法來解決這個問題,通過維護四個邊界變數,按照右→下→左→上的順序遍歷,並在每次遍歷後收縮對應的邊界。
解法 #
從邊界開始收縮
- 初始化四個邊界變數:
top、bottom、left、right - 按照順時針順序遍歷:
- 從左到右遍歷頂行
- 從上到下遍歷右列
- 從右到左遍歷底行(需要檢查上下邊界)
- 從下到上遍歷左列(需要檢查左右邊界)
- 每次遍歷後收縮對應的邊界
- 當邊界交叉時停止遍歷
步驟 #
- 初始化邊界:
top = 0:頂行邊界bottom = matrix.length-1:底行邊界left = 0:左列邊界right = matrix[0].length-1:右列邊界
- 螺旋遍歷:
- 從左到右遍歷頂行,遍歷完後
top++ - 從上到下遍歷右列,遍歷完後
right-- - 從右到左遍歷底行(檢查
top <= bottom),遍歷完後bottom-- - 從下到上遍歷左列(檢查
left <= right),遍歷完後left++
- 從左到右遍歷頂行,遍歷完後
- 停止條件:
- 當
top > bottom或left > right時停止
- 當
例子說明 #
matrix = [[1,2,3],[4,5,6],[7,8,9]]
初始矩陣:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]| 步驟 | 方向 | 遍歷範圍 | 結果 | 邊界更新 |
|---|---|---|---|---|
| 初始化 | - | - | [] | top=0, bottom=2, left=0, right=2 |
| Step 1 | 左→右 | matrix[0][0:2] |
[1,2,3] | top++ → top=1 |
| Step 2 | 上→下 | matrix[1:2][2] |
[1,2,3,6,9] | right-- → right=1 |
| Step 3 | 右→左 | matrix[2][1:0] |
[1,2,3,6,9,8,7] | bottom-- → bottom=1 |
| Step 4 | 下→上 | matrix[1][0] |
[1,2,3,6,9,8,7,4] | left++ → left=1 |
| Step 5 | 左→右 | matrix[1][1] |
[1,2,3,6,9,8,7,4,5] | top++ → top=2 |
最終結果: [1,2,3,6,9,8,7,4,5]
各步驟矩陣狀態:
Step 1 - 遍歷頂行:
[1, 2, 3] ← 遍歷完成
[4, 5, 6]
[7, 8, 9]邊界更新:top++ → top=1
Step 2 - 遍歷右列:
[1, 2, 3]
[4, 5, 6] ← 遍歷完成
[7, 8, 9] ← 遍歷完成邊界更新:right– → right=1
Step 3 - 遍歷底行:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9] ← 遍歷完成邊界更新:bottom– → bottom=1
Step 4 - 遍歷左列:
[1, 2, 3]
[4, 5, 6] ← 遍歷完成
[7, 8, 9]邊界更新:left++ → left=1
Step 5 - 遍歷中心元素:
[1, 2, 3]
[4, 5, 6] ← 遍歷完成
[7, 8, 9]邊界更新:top++ → top=2
完整程式碼 #
java
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
// 初始化四個邊界
int top = 0;
int bottom = matrix.length - 1;
int left = 0;
int right = matrix[0].length - 1;
while (top <= bottom && left <= right) {
// 從左到右遍歷頂行
for (int col = left; col <= right; col++) {
res.add(matrix[top][col]);
}
top++;
// 從上到下遍歷右列
for (int row = top; row <= bottom; row++) {
res.add(matrix[row][right]);
}
right--;
// 從右到左遍歷底行,需要檢查上下邊界
if (top <= bottom) {
for (int col = right; col >= left; col--) {
res.add(matrix[bottom][col]);
}
}
bottom--;
// 從下到上遍歷左列,需要檢查左右邊界
if (left <= right) {
for (int row = bottom; row >= top; row--) {
res.add(matrix[row][left]);
}
}
left++;
}
return res;
}
}時間複雜度 #
- 時間複雜度:
O(m × n),其中 m 和 n 分別是矩陣的行數和列數,需要遍歷每個元素一次 - 空間複雜度:
O(1),除了結果列表外,只使用了常數個變數