矩阵中的搜索

矩阵中的搜索
例题一:太平洋大西洋水流问题
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);
            }
        }
    }
};

这个题我还看到有多源搜索,不过我也没有看太明白里面的思路,等弄清楚了再更改。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值