快轉到主要內容
leetcode 417 - Pacific Atlantic Water Flow

leetcode 417 - Pacific Atlantic Water Flow

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

題目
#

leetcode 417 - Pacific Atlantic Water Flow (題目說明請點連結)

題目簡述
#

給一個 m x n 的整數矩陣 heights,其中 heights[i][j] 表示該位置的高度。請找出所有既能流向太平洋又能流向大西洋的位置。
水流只能從高處流向低處或相同高度,且只能流向上下左右四個方向。

範例
#

Example 1:

Input: heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
Output: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
Explanation: 這些位置既能流向太平洋又能流向大西洋。
5 × 5 高度陣列:

┌───┬───┬───┬───┬───┐
│ 1 │ 2 │ 2 │ 3 │ 5 │ ← 太平洋邊界
├───┼───┼───┼───┼───┤
│ 3 │ 2 │ 3 │ 4 │ 4 │
├───┼───┼───┼───┼───┤
│ 2 │ 4 │ 5 │ 3 │ 1 │
├───┼───┼───┼───┼───┤
│ 6 │ 7 │ 1 │ 4 │ 5 │
├───┼───┼───┼───┼───┤
│ 5 │ 1 │ 1 │ 2 │ 4 │
└───┴───┴───┴───┴───┘
    大西洋邊界

答案位置(既能流向太平洋又能流向大西洋):
[0,4] [1,3] [1,4] [2,2] [3,0] [3,1] [4,0]

Example 2:

Input: heights = [[2,1],[1,2]]
Output: [[0,0],[0,1],[1,0],[1,1]]
Explanation: 所有位置都能同時流向太平洋和大西洋。
2 × 2 高度陣列:

┌───┬───┐
│ 2 │ 1 │ ← 太平洋邊界
├───┼───┤
│ 1 │ 2 │
└───┴───┘
大西洋邊界

答案位置(所有位置都能同時流向太平洋和大西洋):
[0,0] [0,1] [1,0] [1,1]

解題思路
#

這題要求我們找出所有既能流向太平洋又能流向大西洋的位置。我們可以使用深度優先搜尋(DFS)來解決這個問題,具體方法是從邊界開始反向搜尋,找出所有能到達邊界的位置。

解法
#

DFS

  1. 創建兩個布林陣列 pacificatlantic 來記錄每個位置是否能到達對應的海洋
  2. 從太平洋邊界(左邊界和上邊界)開始 DFS,標記所有能到達太平洋的位置
  3. 從大西洋邊界(右邊界和下邊界)開始 DFS,標記所有能到達大西洋的位置
  4. 找出同時能到達兩個海洋的位置

步驟
#

  • 初始化:
    • 創建 pacificatlantic 布林陣列
    • 設定方向陣列 dirs 表示上下左右四個方向
  • 太平洋邊界 DFS:
    • 從左邊界(i, 0)開始 DFS
    • 從上邊界(0, i)開始 DFS
  • 大西洋邊界 DFS:
    • 從右邊界(i, n-1)開始 DFS
    • 從下邊界(m-1, i)開始 DFS
  • 收集結果:
    • 找出同時為 true 的位置
    • 返回結果列表

例子說明
#

heights = [[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]

┌───┬───┬───┬───┬───┐
│ 1 │ 2 │ 2 │ 3 │ 5 │ ← 太平洋邊界
├───┼───┼───┼───┼───┤
│ 3 │ 2 │ 3 │ 4 │ 4 │
├───┼───┼───┼───┼───┤
│ 2 │ 4 │ 5 │ 3 │ 1 │
├───┼───┼───┼───┼───┤
│ 6 │ 7 │ 1 │ 4 │ 5 │
├───┼───┼───┼───┼───┤
│ 5 │ 1 │ 1 │ 2 │ 4 │
└───┴───┴───┴───┴───┘
    大西洋邊界
步驟 操作 pacific 陣列 atlantic 陣列 說明
初始化 - 5x5 全為 false 5x5 全為 false 創建兩個布林陣列
太平洋邊界 DFS 從左邊界開始 標記左邊界可達位置 - 從左邊界開始反向搜尋
太平洋邊界 DFS 從上邊界開始 標記上邊界可達位置 - 從上邊界開始反向搜尋
大西洋邊界 DFS 從右邊界開始 - 標記右邊界可達位置 從右邊界開始反向搜尋
大西洋邊界 DFS 從下邊界開始 - 標記下邊界可達位置 從下邊界開始反向搜尋
收集結果 找出交集 - - 找出同時為 true 的位置

最終結果: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]

完整程式碼
#

java
class Solution {
    // 矩陣的行數和列數
    int m, n;
    // 記錄每個位置是否能到達太平洋和大西洋
    boolean[][] pacific, atlantic;
    // 四個方向的偏移量:下、上、右、左
    int[][] dirs = {{1,0}, {-1,0}, {0,1}, {0,-1}};
    
    public List<List<Integer>> pacificAtlantic(int[][] heights) {
        this.m = heights.length;
        this.n = heights[0].length;
        // 初始化兩個布林陣列
        pacific = new boolean[m][n];
        atlantic = new boolean[m][n];

        // 從太平洋邊界開始 DFS
        for(int i = 0; i < m; i++){
            dfs(heights, i, 0, pacific);    // 左邊界(太平洋)
            dfs(heights, i, n-1, atlantic); // 右邊界(大西洋)
        }
        
        // 從大西洋邊界開始 DFS
        for(int i = 0; i < n; i++){
            dfs(heights, 0, i, pacific);    // 上邊界(太平洋)
            dfs(heights, m-1, i, atlantic); // 下邊界(大西洋)
        }

        // 收集結果:找出同時能到達兩個海洋的位置
        List<List<Integer>> ans = new ArrayList<>();
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(pacific[i][j] && atlantic[i][j]){
                    ans.add(Arrays.asList(i, j));
                }
            }
        }
        return ans;
    }

    // DFS 方法:從邊界開始反向搜尋
    public void dfs(int[][] heights, int x, int y, boolean[][] visited){
        // 標記當前位置為已訪問
        visited[x][y] = true;
       
        // 嘗試四個方向
        for(int[] dir : dirs){
            int nx = x + dir[0], ny = y + dir[1];

            // 檢查邊界條件和是否已訪問
            if(nx < 0 || ny < 0 || nx >= m || ny >= n || visited[nx][ny] == true){
                continue;
            }

            // 檢查水流方向:只能從高處流向低處或相同高度
            if(heights[nx][ny] >= heights[x][y]){
                dfs(heights, nx, ny, visited);
            }
        }
    }
}

時間複雜度
#

  • 時間複雜度O(m × n),其中 m 和 n 是矩陣的行數和列數,需要遍歷整個矩陣來標記可達位置
  • 空間複雜度O(m × n),需要兩個 boolean 陣列來記錄可達性:O(m × n)

相關文章

leetcode 79 - Word Search
類別 
Leetcode
標籤 
Java Leetcode Medium DFS Problem Blind75
leetcode 200 - Number of Islands
類別 
Leetcode
標籤 
Java Leetcode Medium DFS Problem Blind75
leetcode 105 - Construct Binary Tree from Preorder and Inorder Traversal
類別 
Leetcode
標籤 
Java Leetcode Medium Tree Problem Blind75