LeetCode从低效到高效,点击
一、题目描述:
题目要求
给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。 规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。
请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。
来源:力扣(LeetCode)链接
示例
给定下面的 5x5 矩阵:
太平洋 ~ ~ ~ ~ ~
~ 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]] (上图中带括号的单元).
二、思路分析:
这是一道DFS且不用回溯法的题,我最开始的时候相当的方法是直接找到中间那些高点,发现很困难,但是反过来如果从海往内陆搜索就相对容易多了,从四周向内陆搜索,凡是相邻的且比自己大的都代表能够流过,这样使用多点DFS,将两个大洋能够流过的矩阵做与就能知道这个矩阵相对的高点在哪里了。
三、AC 代码:
这个递归写法是假设所有送到递归这里的都是合法可走的格子
// 88 ms 23.2 MB
vector<vector<int>> dir{{-1,0},{1,0},{0,1},{0,-1}};
void dfsFlow(vector<vector<int>> &matrix,vector<vector<bool>> &ans,int idx,int jdx){
int h = matrix.size(),w=matrix[0].size();
ans[idx][jdx] = true;
for(auto d:dir){
int x = idx+d[0];
int y = jdx+d[1];
if(x>=0&&x<h&&y>=0&&y<w&&!ans[x][y]){
// cout<<x<<" "<<y<<" "<<idx<<" "<<jdx<<endl;
if(matrix[x][y]>=matrix[idx][jdx])
dfsFlow(matrix,ans,x,y);
}
}
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix) {
int h = matrix.size();
vector<vector<int>> out;
if(!h){
return out;
}
int w = matrix[0].size();
vector<vector<bool>> ans(h,vector<bool>(w,false));
vector<vector<bool>> ans2(h,vector<bool>(w,false));
for(int i=0;i<h;i++){
// 左侧
// cout<<"左侧"<<endl;
dfsFlow(matrix,ans,i,0);
// 右侧
// cout<<"右侧"<<endl;
dfsFlow(matrix,ans2,i,w-1);
}
for(int i=0;i<w;i++){
// 上侧
dfsFlow(matrix,ans,0,i);
// 下侧
dfsFlow(matrix,ans2,h-1,i);
}
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
if(ans[i][j]&&ans2[i][j]){
out.push_back({i,j});
}
}
}
return out;
}
四、总结:
当按照题目要求正向思考困难时,可以考虑反向思考是不是会更加容易。
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情