有一个 m × n 的矩形岛屿,与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界,而 “大西洋” 处于大陆的右边界和下边界。
这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights , heights[r][c] 表示坐标 (r, c) 上单元格 高于海平面的高度 。
岛上雨水较多,如果相邻单元格的高度 小于或等于 当前单元格的高度,雨水可以直接向北、南、东、西流向相邻单元格。水可以从海洋附近的任何单元格流入海洋。
返回网格坐标 result 的 2D 列表 ,其中 result[i] = [ri, ci] 表示雨水从单元格 (ri, ci) 流动 既可流向太平洋也可流向大西洋 。
示例 1:
- 输入: 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]]
- 输出: [[0,4],[1,3],[1,4],[2,2],[3,0],[3,1],[4,0]]
示例 2:
- 输入: heights = [[2,1],[1,2]]
- 输出: [[0,0],[0,1],[1,0],[1,1]]
思路:
从太平洋和大西洋的两边开始遍历深搜,相当于每次逆流而上找从海洋到陆地的道路,然后把两条道路的公共部分标记出来,这些就是能同时到达两个两个海洋的点。
说一下我刚开始做的时候的误区:
一开始我从两边遍历的时候,想的是找到一条能直接到另一个海的路,然后两边遍历完找公共部分,这样是不对的,因为我们的目的不是让一条海水流到另一个海,而是在岛上有一个点能流向两个海,所以这个路径是不连通的,从该点开始断开。
然后就是在逆流而上处理的时候,应该是判断heights[x][y]>heights[fx][fy]无效,因为此时我们是逆着路走的,并不是海水到岛里,而是岛上的雨水流到大海中,所以这里的判断是反过来的。
class Solution {
private:
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
void bfs(vector<vector<int>>& heights,vector<vector<bool>>& visit,int x,int y){
if(visit[x][y])return;
visit[x][y]=true;
for(int i=0;i<4;i++){
int fx=x+dx[i];
int fy=y+dy[i];
if(fx<0 || fy<0 || fx>=heights.size() || fy>=heights[0].size())continue;
if(heights[x][y]>heights[fx][fy])continue;//这里因为是逆流而上的判断,所以之前的要大于新的
bfs(heights,visit,fx,fy);
}
}
public:
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
int n=heights.size();
int m=heights[0].size();
vector<vector<bool>> pacific=vector<vector<bool>>(n,vector<bool>(m,false));
vector<vector<bool>> atlantic=vector<vector<bool>>(n,vector<bool>(m,false));
//最上和最下
for(int i=0;i<m;i++){
bfs(heights,pacific,0,i);
bfs(heights,atlantic,n-1,i);
}
//最左和最右
for(int i=0;i<n;i++){
bfs(heights,pacific,i,0);
bfs(heights,atlantic,i,m-1);
}
vector<vector<int>> ans;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(pacific[i][j]&&atlantic[i][j]){
ans.push_back({i,j});
}
}
}
return ans;
}
};