太平洋大西洋水流問題(力扣第417題)

2022-06-16 11:42:09 字數 3460 閱讀 4965

題目:

給定乙個 m x n 的非負整數矩陣來表示一片大陸上各個單元格的高度。「太平洋」處於大陸的左邊界和上邊界,而「大西洋」處於大陸的右邊界和下邊界。

規定水流只能按照上、下、左、右四個方向流動,且只能從高到低或者在同等高度上流動。

請找出那些水流既可以流動到「太平洋」,又能流動到「大西洋」的陸地單元的座標。

輸出座標的順序不重要

m 和 n 都小於150

示例:

給定下面的 5x5 矩陣:

太平洋 ~ ~ ~ ~ ~

~ 12

23 (5) *

~ 32

3 (4) (4) *

~ 24 (5) 3

1 *~ (6) (7) 1

45 *

~ (5) 112

4 ** * * * *大西洋

返回:[[

0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上圖中帶括號的單元).

分析:

由題意可知,水流可以走四個方向:

上下左右;驅動水流動的條件是當前陸地單元的高度大於等於下一步要流向的陸地單元的高度;其中還有兩個比較特殊的陸地單元,那就是位於兩個海洋交界位置的點,左下角和右上角的陸地單元,它們直接毗鄰兩個海洋,所以可以直接流向這兩個海洋。

那麼還是可以通過深度優先遍歷的方法來解決,只不過這裡不再需要從乙個點一直遍歷乙個完整的連通分量,而是只要能夠確認這個點可達兩個海洋即可停止深度優先遍歷。

其中,遍歷的過程,當遇到(0,j)或者(i,0)這些點時,那麼就說明可達太平洋;當遇到(m-1,j)或者(i,n-1)這些點時,說明可達大西洋。這裡我們借助於dfs的非遞迴遍歷,設定乙個訪問標記陣列,用於標記從當前給定的點出發時,矩陣中的點是否已被訪問,然後設定兩個標記變數,分別用於標記大西洋和太平洋是否可達,如果二者皆可達,那麼說明其就是符合要求的座標,否則不是。

**:

private

intm;

private

intn;

public list> pacificatlantic(int

matrix)

m =matrix.length;

n = matrix[0].length;

arraylist

> reslist = new arraylist<>();

list

midres;

for (int i = 0; i < m; i++) }}

return

reslist;

}private

boolean flowdfs(int matrix,int i,int

j)

boolean isvisited = new

boolean

[m][n];

int dirs = ,,,};

stack

> stack = new stack<>();

stack.push(

new pair<>(i,j));

isvisited[i][j] = true

;

int flag = 0;

int flag_west = 0;

while (!stack.isempty())

if (cur_i == m-1 || cur_j == n-1)

int count = 0;

for (int

dir : dirs)

if (matrix[cur_i][cur_j] >= matrix[next_i][next_j] && !isvisited[next_i][next_j])

else

if (next_i == m || next_j == n-1)

stack.push(

new pair<>(next_i,next_j));

count = 1;

break

; }

}if (flag == 1 && flag_west == 1)

if (count == 0)

}return

false

; }

程式雖然通過了,但是效能十分的不好,這裡我也參考了cyc2018大神的解法,我感覺很有借鑑意義,那麼在這裡記錄一下大神的解法思想:

它主要是設定兩個訪問標記陣列,分別用於記錄可以到達大西洋和太平洋的陸地單元,它們是布林型別的,只要對應位置的元素值為true時,那麼就說明這個陸地單元可達相應的「海洋」;而是如何進行遍歷的呢?我們來分析,首先乙個陸地單元如果可達某個海洋,那麼」沿海「的陸地單元也必然」反向「可達該陸地單元(反向可達的意思是從低的位置流向高的位置),所以,就可以從」沿海「的陸地單元出發,進行dfs遍歷,此時我們深度優先遍歷的結果要求不能中斷,要竭盡所有可以到達的點,那麼最終得到的連通分量中的點都是可以到達起始點所挨著的那個」海洋的「,所以,我們就可以只遍歷邊界的點了,而不要每個點都進行乙個dfs點遍歷然後判斷是否可達兩個海洋。

我們分別從兩個海洋的各自擁有的兩個沿海邊界出發,凡是遍歷到的點,就在對應的訪問標記陣列對應的元素值設定為true,最終兩個標記陣列相同點都為true的陸地單元,就是所求的座標。

**如下:

private

intm, n;

private

int matrix;

private

int direction = , , , };

public list> pacificatlantic(int

matrix)

m =matrix.length;

n = matrix[0].length;

this.matrix =matrix;

boolean canreachp = new

boolean

[m][n];

boolean canreacha = new

boolean

[m][n];

for (int i = 0; i < m; i++)

for (int i = 0; i < n; i++)

for (int i = 0; i < m; i++) }}

return

ret;

}private

void dfs(int r, int c, boolean

canreach)

canreach[r][c] = true

;

for (int

d : direction)

dfs(nextr, nextc, canreach);

}}

參考自:

417太平洋大西洋水流問題

採用逆向思維,從陣列的最外邊開始遍歷,向陣列中心開始遍歷,如果太平洋和大西洋都被訪問過,那麼當前節點就就符合題目條件。class solution,bool iseffective int x,int y void dfs int x,int y,int pre,vector bool shuzu,...

417 太平洋大西洋水流問題

給定乙個 m x n 的非負整數矩陣來表示一片大陸上各個單元格的高度。太平洋 處於大陸的左邊界和上邊界,而 大西洋 處於大陸的右邊界和下邊界。規定水流只能按照上 下 左 右四個方向流動,且只能從高到低或者在同等高度上流動。請找出那些水流既可以流動到 太平洋 又能流動到 大西洋 的陸地單元的座標。目前...

417 太平洋大西洋水流問題

典型的搜尋演算法,不過這次搜尋的目標有兩個,到達太平洋和大西洋。需要寫兩個dfs遞迴函式。演算法流程 遍歷圖中所有點,呼叫深度遞迴函式。如果該點既能到達太平洋又能夠到達大西洋。那麼將這個點加入結果集。返回結果集合 這裡的遞迴算是深度優先遍歷的模板步驟吧。不過這裡標記是否訪問用了乙個小技巧,修改原陣列...