快轉到主要內容
leetcode 54 - Spiral Matrix

leetcode 54 - Spiral Matrix

·
類別 
Leetcode
標籤 
Java Leetcode Medium Array Problem Blind75
Eason Chiu
作者
Eason Chiu
一個不做筆記就容易忘記的工程師
目錄

題目
#

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 ← 9

Example 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

解題思路
#

這題要求我們按照順時針螺旋順序遍歷矩陣。我們可以使用邊界收縮法來解決這個問題,通過維護四個邊界變數,按照右→下→左→上的順序遍歷,並在每次遍歷後收縮對應的邊界。

解法
#

從邊界開始收縮

  1. 初始化四個邊界變數:topbottomleftright
  2. 按照順時針順序遍歷:
    • 從左到右遍歷頂行
    • 從上到下遍歷右列
    • 從右到左遍歷底行(需要檢查上下邊界)
    • 從下到上遍歷左列(需要檢查左右邊界)
  3. 每次遍歷後收縮對應的邊界
  4. 當邊界交叉時停止遍歷

步驟
#

  • 初始化邊界:
    • top = 0:頂行邊界
    • bottom = matrix.length-1:底行邊界
    • left = 0:左列邊界
    • right = matrix[0].length-1:右列邊界
  • 螺旋遍歷:
    • 從左到右遍歷頂行,遍歷完後 top++
    • 從上到下遍歷右列,遍歷完後 right--
    • 從右到左遍歷底行(檢查 top <= bottom),遍歷完後 bottom--
    • 從下到上遍歷左列(檢查 left <= right),遍歷完後 left++
  • 停止條件:
    • top > bottomleft > 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),除了結果列表外,只使用了常數個變數

相關文章

leetcode 128 - Longest Consecutive Sequence
類別 
Leetcode
標籤 
Java Leetcode Medium Array Problem Blind75
leetcode 152 - Maximum Product Subarray
類別 
Leetcode
標籤 
Java Leetcode Medium Array Problem Blind75
leetcode 238 - Product of Array Except Self
類別 
Leetcode
標籤 
Java Leetcode Medium Array Problem Blind75