矩阵中的搜索
例题一:太平洋大西洋水流问题
https://leetcode-cn.com/problems/pacific-atlantic-water-flow/submissions/
题目分析:
仔细理解题目意思可知,岛屿被分为很多个小块,现在因为各小块的海拔不同,所以岛屿上不同小块的雨水会流向不同的海洋,我们需要找到的就是雨水既可以流向大西洋又可以流向太平洋的小块。
从岛屿流向海洋的思路考虑:
水往低处流,如果一个小块周围的小块海拔都比他小(或等于)则这个小块上的雨水就可以向外流。但是在这块岛屿中我们不能确定从哪一个小块开始。所以我们逆向思考。
从海洋流向岛屿考虑:
这是题目意图的逆向,所以我们应该遵循水往高处流的原则。海水从海洋开始,若周围的海拔比他高,则可以流向下一个小块,若海拔比他低,则海水不能流向下一个小块。
海水从矩阵的四周向内流,两个海洋的海水在流到一定位置便不能往下流,而我们只需要找到两种海水均能到达的小块即可。
参考代码:
class Solution {
public:
vector<vector<int>>P,A,res;
int n,m;
vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
n=heights.size();
m=heights[0].size();
P=A=vector<vector<int>>(n,vector<int>(m,0));//P,A两个矩阵初始时矩阵内元素均为0
for(int i=0;i<n;++i){
dfs(heights,P,i,0);
dfs(heights,A,i,m-1);
}//从左右两边的边界开始出发
for(int j=0;j<m;++j){
dfs(heights,P,0,j);
dfs(heights,A,n-1,j);
}//从上下两边的边界开始出发搜索
return res;
}
void dfs(vector<vector<int>>&heights,vector<vector<int>>&visited,int i,int j){
if(visited[i][j])return;
visited[i][j]=1;//对到达的小块进行标记
if(P[i][j]&&A[i][j])res.push_back({i,j});//两种海水都能到达则将小块坐标加入到res中
if(i-1>=0&&heights[i-1][j]>=heights[i][j])dfs(heights,visited,i-1,j);
if(i+1<n&&heights[i+1][j]>=heights[i][j])dfs(heights,visited,i+1,j);
if(j-1>=0&&heights[i][j-1]>=heights[i][j])dfs(heights,visited,i,j-1);
if(j+1<m&&heights[i][j+1]>=heights[i][j])dfs(heights,visited,i,j+1);
}
};
例题二:墙与门
题目链接:https://leetcode-cn.com/problems/walls-and-gates/
题目分析:这个题和上面题目的思路非常相似,也是逆向思考。从门开始搜索,在搜索的时候到一个空房间就更新距离。到后面不同的门搜索到同一个空房间时若距离更小,则更新该空房间的值。
class Solution {
public:
void wallsAndGates(vector<vector<int>>& rooms) {
for(int i=0;i<rooms.size();i++){
for(int j=0;j<rooms[0].size();j++){
if(rooms[i][j]==0){
dfs(rooms,i,j,0);
}
}
}
}
void dfs(vector<vector<int>>&rooms,int x,int y,int dis){
if(x-1>=0&&rooms[x-1][y]>0){//搜索门左边
if(rooms[x-1][y]>dis+1){
rooms[x-1][y]=dis+1;
dfs(rooms,x-1,y,dis+1);
}
}
if(x+1<rooms.size()&&rooms[x+1][y]>0){//搜索右边
if(rooms[x+1][y]>dis+1){
rooms[x+1][y]=dis+1;
dfs(rooms,x+1,y,dis+1);
}
}
if(y-1>=0&&rooms[x][y-1]>0){//向上搜索
if(rooms[x][y-1]>dis+1){
rooms[x][y-1]=dis+1;
dfs(rooms,x,y-1,dis+1);
}
}
if(y+1<rooms[0].size()&&rooms[x][y+1]>0){//向下搜索
if(rooms[x][y+1]>dis+1){
rooms[x][y+1]=dis+1;
dfs(rooms,x,y+1,dis+1);
}
}
}
};
这个题我还看到有多源搜索,不过我也没有看太明白里面的思路,等弄清楚了再更改。