Leetcode 417 題 太平洋大西洋水流問(wèn)題

題目描述

給定一個(gè) m x n 的非負(fù)整數(shù)矩陣來(lái)表示一片大陸上各個(gè)單元格的高度。“太平洋”處于大陸的左邊界和上邊界,而“大西洋”處于大陸的右邊界和下邊界。

規(guī)定水流只能按照上、下、左、右四個(gè)方向流動(dòng),且只能從高到低或者在同等高度上流動(dòng)。

請(qǐng)找出那些水流既可以流動(dòng)到“太平洋”,又能流動(dòng)到“大西洋”的陸地單元的坐標(biāo)。

示例:
給定下面的 5x5 矩陣:


image.png

返回:[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上圖中帶括號(hào)的單元)。


思路分析

這道題所給出的二維矩陣,上邊界和左邊界代表太平洋,下邊界和右邊界代表大西洋。矩陣中的數(shù)字代表高度,水只能從高往低或者等高位上流動(dòng),需要我們求出哪些地方的水可以流到兩個(gè)地方。例如矩陣中的 7,既可以流到太平洋,又可以流到大西洋,我們需要的就是找到這些位置。

我們可以用兩個(gè) boolean 類型的二維數(shù)組來(lái)分別存儲(chǔ)水是否可以流到太平洋和大西洋,只要取它們的交集,如果兩個(gè)二維數(shù)組中某個(gè)點(diǎn)的值都是 true,那么說(shuō)明這個(gè)點(diǎn)的水既可以流到太平洋,也可以流到大西洋,而這就是我們需要的結(jié)果。

如何生成這兩個(gè)二維數(shù)組呢?我們需要從一個(gè)點(diǎn)開(kāi)始,到上下左右,去找比它低或者等于它的值,直到找到太平洋或者大西洋。事實(shí)上二維矩陣的邊界就連接著海洋,我們可以從邊界開(kāi)始,進(jìn)行反向操作,去找比它高或者等于它的值,也是可以完成搜索的。

我們可以通過(guò)深度優(yōu)先搜索進(jìn)行查找,如果相鄰的值比當(dāng)前值低,我們就直接返回,只有比當(dāng)前值高或者等于當(dāng)前值,我們才會(huì)繼續(xù) dfs。


代碼描述
class Solution {
    public List<List<Integer>> pacificAtlantic(int[][] matrix) {
        List<List<Integer>> result = new ArrayList<>();
        int m = matrix.length;
        if (m == 0) return result;
        int n = matrix[0].length;

        // 定義 table1、table2 存儲(chǔ)是否流入太平洋
        boolean[][] table1 = new boolean[m][n];
        boolean[][] table2 = new boolean[m][n];

        // 能否觸達(dá)上、下
        for (int i = 0; i < n; i++) {
            dfs(matrix, 0, i, matrix[0][i], table1);
            dfs(matrix, m - 1, i, matrix[m - 1][i], table2);
        }

        // 能否觸達(dá)左右
        for (int i = 0; i < m; i++) {
            dfs(matrix, i, 0, matrix[i][0], table1);
            dfs(matrix, i, n - 1, matrix[i][n - 1], table2);
        }

        // 取出都能觸達(dá)的點(diǎn)
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (table1[i][j] && table2[i][j]) {
                    List<Integer> list = new ArrayList<>();
                    list.add(i);
                    list.add(j);
                    result.add(list);
                }
            }
        }

        return result;
    }

    public void dfs(int[][] matrix, int x, int y, int pre, boolean[][] table) {
        if (x < 0 || x >= matrix.length || y < 0 || y >= matrix[0].length ||
                matrix[x][y] < pre || // 當(dāng)前值小于上一個(gè)值
                table[x][y] // 當(dāng)前值已經(jīng)被標(biāo)記
        ) return;

        table[x][y] = true;

        // 上下左右
        dfs(matrix, x - 1, y, matrix[x][y], table);
        dfs(matrix, x + 1, y, matrix[x][y], table);
        dfs(matrix, x, y - 1, matrix[x][y], table);
        dfs(matrix, x, y + 1, matrix[x][y], table);
    }
}


歡迎關(guān)注

技術(shù)號(hào):小猿君的算法筆記

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容