417. Pacific Atlantic Water Flow
連續五天都是 matrix 相關的問題啊…
這題一開始就決定用深度優先搜尋配合遞迴的解法,使用正向搜尋的邏輯,也就是題目所說的:假如 heights(x, y) >= heights(x + 1, y) ,河流就可以往 x + 1 的方向流動,結果發現處理重複尋訪的問題實在很煩人,空間複雜度平白多了 O(m*n) 不說,程式邏輯也是奇醜無比,後來靈光一閃,其實可以用反向搜尋,也就是從岸邊開始往內陸尋找上游,這樣就可以完全無視重複尋訪的問題,有點 DP 的感覺…
1
2
3
4
5
6
7
8
9
10
11
| void flow(vector<vector<int>>& h, vector<vector<bool>>& t, int row, int col) {
if(row < 0 || row > m - 1 || col < 0 || col > n - 1) return;
if (!t[row][col]) {
t[row][col] = true;
if (row - 1 >= 0 && h[row][col] <= h[row - 1][col]) flow(h, t, row - 1, col);
if (col - 1 >= 0 && h[row][col] <= h[row][col - 1]) flow(h, t, row, col - 1);
if (row + 1 < m && h[row][col] <= h[row + 1][col]) flow(h, t, row + 1, col);
if (col + 1 < n && h[row][col] <= h[row][col + 1]) flow(h, t, row, col + 1);
}
}
|
可以看到規則變成 heights(x, y) <= heights(x + 1, y) 才繼續往 x + 1 的方向走,反正就是一路往上,如果已經是 true 就直接離開,否則先標記成 true 再繼續溯源。這裡的參數 h 就是原始題目輸入的 heights , t 則是表示座標 (x, y) 可否流至 Pacific Ocean 或是 Atlantic Ocean 的布林陣列,遞迴的起點就是從岸邊開始
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| static int m, n;
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
m = heights.size(), n = heights[0].size();
vector<vector<bool>> toPac(m, vector<bool>(n, false));
vector<vector<bool>> toAtl(m, vector<bool>(n, false));
vector<vector<int>> ans;
for (int p = 0; p < m; p++)
for (int q = 0; q < n; q++) {
if (p == m - 1 || q == n - 1)
flow(heights, toAtl, p, q);
if (p == 0 || q == 0)
flow(heights, toPac, p, q);
}
for (int x = 0; x < m; x++)
for (int y = 0; y < n; y++)
if (toPac[x][y] && toAtl[x][y])
ans.push_back({ x, y });
return ans;
}
|
因為 Pacific Ocean 是在西北方,所以岸邊座標就是 row = 0 和 column = 0 ,而 Atlantic Ocean 是在東南方,所以從 row = m - 1 和 column = n - 1 的位置開始遞迴,最後找出兩個矩陣的交集就是答案了