问题:
给定一个二维数组,代表一块大陆的海拔,
数组左边和上边为太平洋,右边和下边为大西洋,
对于大陆上的每一个点,有水向海拔=<自己的方向流动,求既能流进太平洋,又能流进大西洋的坐标位置。
Example: Given the following 5x5 matrix: Pacific ~ ~ ~ ~ ~ ~ 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 * * * * * * Atlantic Return: [[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (positions with parentheses in above matrix). Note: 1.The order of returned grid coordinates does not matter. 2.Both m and n are less than 150.
解法:BFS,DFS
解法一:BFS
思想:使用两个queue,分别记录:太平洋Pcf_q,大西洋Atl_q
逆着水流,从沿岸开始,向海拔高的地方进行遍历,当有水流过,则记录水流数组Pcf,Atl对应cell为true。否则为false。
BFS遍历整个大陆后,
对比两个水流数组Pcf,Atl
同样的cell中,都为true,则符合题意。
代码参考:
1 class Solution { 2 public: 3 int m,n; 4 void bfs(queue<pair<int,int>>& q, vector<vector<bool>>& visited, vector<vector<int>>& matrix) { 5 int dir[5] = {1,0,-1,0,1}; 6 int cur_i, cur_j, x, y; 7 while(!q.empty()) { 8 int sz = q.size(); 9 for(int i=0; i<sz; i++) { 10 cur_i = q.front().first; 11 cur_j = q.front().second; 12 q.pop(); 13 for(int j=1; j<5; j++) { 14 x = cur_i+dir[j-1]; 15 y = cur_j+dir[j]; 16 if(x<0 || x>=n || y<0 || y>=m 17 || visited[x][y] || matrix[x][y]<matrix[cur_i][cur_j]) continue; 18 q.push({x,y}); 19 visited[x][y]=true; 20 } 21 } 22 } 23 return; 24 } 25 vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) { 26 vector<vector<int>> res; 27 queue<pair<int,int>> Pcf_q, Atl_q; 28 n = matrix.size(); 29 if(n==0) return res; 30 m = matrix[0].size(); 31 vector<vector<bool>> Pcf(n,vector<bool>(m,false)); 32 vector<vector<bool>> Atl(Pcf);//visited 33 //add board to queue 34 for(int i=0; i<n; i++) { 35 Pcf_q.push({i,0});//left 36 Pcf[i][0] = true; 37 Atl_q.push({i,m-1});//right 38 Atl[i][m-1] = true; 39 } 40 for(int j=0; j<m; j++) { 41 Pcf_q.push({0,j});//up 42 Pcf[0][j] = true; 43 Atl_q.push({n-1,j});//bottom 44 Atl[n-1][j] = true; 45 } 46 bfs(Pcf_q, Pcf, matrix); 47 bfs(Atl_q, Atl, matrix); 48 for(int i=0; i<n; i++) { 49 for(int j=0; j<m; j++) { 50 if(Pcf[i][j] && Atl[i][j]) res.push_back({i,j}); 51 } 52 } 53 return res; 54 } 55 };
解法二:DFS
思想:
逆着水流,从沿岸开始,向海拔高的地方进行遍历,
- 从左边+上边所有边缘点开始,向大陆内部DFS遍历,所遍历过满足条件的cell,都是可以流入Pcf太平洋的。
- 从右边+下边所有边缘点开始,向大陆内部DFS遍历,所遍历过满足条件的cell,都是可以流入Atl大西洋的。
DFS:
- 状态:到当前点(i , j)为止,水流都可流过,到达Pcf或Atl
- 选择:四个方向:dir={{0,1},{1,0},{0,-1},{-1,0}},其中满足:除去非法:
- 超出边缘x<0 || x>=n || y<0 || y>=m
- or 访问过 visited[x][y] == true
- or 海拔低于当前点:matrix[x][y]<matrix[i][j]
- 递归退出:在以上选择的时候,最终无可选择即可退出。因此无需多加一步递归退出判断。
当有水流过,则记录水流数组Pcf,Atl对应cell为true。否则为false。
BFS遍历整个大陆后,
对比两个水流数组Pcf,Atl
同样的cell中,都为true,则符合题意。
代码参考:
1 class Solution { 2 public: 3 int m,n; 4 void dfs(vector<vector<bool>>& visited, int i, int j, vector<vector<int>>& matrix) { 5 int dir[5] = {1,0,-1,0,1}; 6 int x, y; 7 visited[i][j] = true; 8 for(int d=1; d<5; d++) { 9 x = i+dir[d-1]; 10 y = j+dir[d]; 11 if(x<0 || x>=n || y<0 || y>=m 12 || visited[x][y] || matrix[x][y]<matrix[i][j]) continue; 13 dfs(visited, x, y, matrix); 14 } 15 return; 16 } 17 vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) { 18 vector<vector<int>> res; 19 n = matrix.size(); 20 if(n==0) return res; 21 m = matrix[0].size(); 22 vector<vector<bool>> Pcf(n,vector<bool>(m,false)); 23 vector<vector<bool>> Atl(Pcf);//visited 24 //Start DFS from board: 25 for(int i=0; i<n; i++) { 26 dfs(Pcf, i, 0, matrix);//left 27 dfs(Atl, i, m-1, matrix);//right 28 } 29 for(int j=0; j<m; j++) { 30 dfs(Pcf, 0, j, matrix);//up 31 dfs(Atl, n-1, j, matrix);//bottom 32 } 33 for(int i=0; i<n; i++) { 34 for(int j=0; j<m; j++) { 35 if(Pcf[i][j] && Atl[i][j]) res.push_back({i,j}); 36 } 37 } 38 return res; 39 } 40 };