深度优先搜索(Depth First Search)学习

不撞"边界"不回头。之前学的,二叉树的前序,中序,后序遍历,其实也是深度优先

员工重要程度

编号代表遍历顺序,由深到浅。
在这里插入图片描述

在这里插入图片描述

/*
// Definition for Employee.
class Employee {
public:
    int id;
    int importance;
    vector<int> subordinates;
};
*/

class Solution {
public:
//也可以不用每次传哈希表,把它当做一个私有成员变量
    int DFS(unordered_map<int,Employee*>& Smap,int id)
    {
        //他输入id,然后我们找到这个员工
       Employee* Ele=Smap[id];
       //拿到他的重要度
       int ret=Ele->importance;

       //从员工这个结构体里,找出他的直系下属id
       for(auto& e:Ele->subordinates)
       {
           //直系下属再去找他自己的直系下属,最后加起来
            ret+=DFS(Smap,e);
       }
        return ret;

    }
    int getImportance(vector<Employee*> employees, int id) {
        unordered_map<int,Employee*> Smap;

        //数组存着员工指针,用哈希表建立id与员工指针之间映射关系
        for(auto& e:employees)
        {
            Smap[e->id]=e;
        }

        return DFS(Smap,id);
    }
};

图像渲染

在这里插入图片描述

class Solution {
private:
    int m;
    int n;
public:
    void DFS(vector<vector<int>>& image, int sr, int sc, int newColor,int oldColor)
    {
          //越界    
          //不等于所给的颜色或者已经标记为新的颜色
          if(sr<0||sc<0||sr>=m||sc>=n ||image[sr][sc]!=oldColor||image[sr][sc]==newColor)
          return; 

          image[sr][sc]=newColor;
          DFS(image,sr+1,sc,newColor,oldColor);   
          DFS(image,sr-1,sc,newColor,oldColor);   
          DFS(image,sr,sc+1,newColor,oldColor);   
          DFS(image,sr,sc-1,newColor,oldColor);   
    } 
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor) {
          m=image.size();
          n=image[0].size();
          //拿到他此时的颜色
          int oldColor=image[sr][sc];
          //对给定节点进行深搜
          DFS(image,sr,sc,newColor,oldColor); 
          return image;     
    }
};

被围绕的区域

先处理边界
在这里插入图片描述
处理完后的矩阵
在这里插入图片描述
里面被包围的O没有处理,边界的O,和与边界相连的O被我们置成了A,所以判断即可
在这里插入图片描述
在这里插入图片描述

class Solution {
private:
    //这样写,函数不用每次都传参了
    int m,n;
public:
    void DFS(vector<vector<char>>& board,int x,int y)
    {
        //         越界              或者 当前不为'0',就返回,即为'0'才继续搜索
       if(x<0 || y<0 || x>=m || y>=n || board[x][y]!='O')
       {
           return;
       }

       //他是边界的'0'或者与边界相连的'0',board[x][y]='0',做标记
       board[x][y]='A';
       DFS(board,x+1,y);
       DFS(board,x-1,y);
       DFS(board,x,y+1);
       DFS(board,x,y-1);

    }
    void solve(vector<vector<char>>& board) {
        //定义成员变量了,还在定义了一遍,无语
        //int  m=board.size();
        //int  n=board[0].size();
        m=board.size();
        n=board[0].size();

        //先处理左右两边,将'0'和连着的'0'做个标记
        for(int i=0;i<m;++i)
        {
           DFS(board,i,0);
           DFS(board,i,n-1);
        }
        //再处理上下两边各减一,将'0'和连着的'0'做个标记
        for(int i=1;i<n-1;++i)
        {
            DFS(board,0,i);
            DFS(board,m-1,i);
        }


        //里面的'0'不会被处理到,因为在DFS中假如你们中间有x隔开,已经在if中处理了

        for(int i=0;i<m;++i)
        {
            for(int j=0;j<n;++j)
            {
                //他是被包围起来的'0'
                if(board[i][j]=='O')
                board[i][j]='X';
                else if(board[i][j]=='A')//他是边界为'0'或者与边界'0'挨着的'0'
                board[i][j]='O';
            }
        }
    }


};

岛屿类问题

岛屿周长

在这里插入图片描述

class Solution {
private:
    int m;
    int n;
    
    int DFS(vector<vector<int>>& grid,int x,int y)
    {
        //遇到边界或者水+1
        if(x<0||y<0||x>=m||y>=n||grid[x][y]==0)
           return 1;
        //再次遇见就不加了
        if(grid[x][y]==2)
           return 0;
        //标记防止重复
        grid[x][y]=2;
        int num=0;
        num+=DFS(grid,x+1,y);
        num+=DFS(grid,x-1,y);
        num+=DFS(grid,x,y+1);
        num+=DFS(grid,x,y-1);

        return num;
    }
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        m=grid.size();
        if(m==0)
           return 0;
        n=grid[0].size();
        int ret=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                //只有一个岛屿,遇到第一个1就开始计算。
                if(grid[i][j]==1)
                {
                  ret=DFS(grid,i,j);  
                }
            }
        }
        return ret;
    }
};

岛屿数量

在这里插入图片描述

class Solution {
private:
    int m;
    int n;
public:
    void DFS(vector<vector<char>>& grid,int x,int y)
    {
        //  越界               
        //  被置为0或者原本就是0
        if(x<0||y<0||x>=m||y>=n||grid[x][y]=='0')
        return;
        
        //1.将1和其连着的1置为0,他们总共只加一次
        //2.将独立的1置为0,每个加一次
        grid[x][y]='0';
        DFS(grid,x+1,y);
        DFS(grid,x-1,y);
        DFS(grid,x,y+1);
        DFS(grid,x,y-1);
    }
    int numIslands(vector<vector<char>>& grid) {
          m=grid.size();
          if(m==0)
          return 0;
          n=grid[0].size();
          int count=0;
          for(int i=0;i<m;i++)
          {
              for(int j=0;j<n;j++)
              {
                  if(grid[i][j]=='1')
                  {
                      count++;
                      DFS(grid,i,j);
                  }
              }
          }
          return count;

    }
};

岛屿最大面积

在这里插入图片描述
在这里插入图片描述

class Solution {
private:
    int m;
    int n;
    int DFS(vector<vector<int>>& grid,int x,int y)
    {
        //越界
        //水,被访问,都不算面积
        if(x<0||y<0||x>=m||y>=n||grid[x][y]==0)
          return 0;
        
        //访问过标记为0,即为水和被访问过都是0
        grid[x][y]=0;
        //每个方格面积至少为1,从1开始。
        int num=1;
        num+=DFS(grid,x+1,y);
        num+=DFS(grid,x-1,y);
        num+=DFS(grid,x,y+1);
        num+=DFS(grid,x,y-1);

        return num;
    }
public:
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m=grid.size();
        if(m==0)
          return 0;
        n=grid[0].size();
        
        int maxArea=0;
        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
                //多个为岛屿,需要求最大
                if(grid[i][j]==1)
                  {
                      int area=DFS(grid,i,j);
                      maxArea=max(maxArea,area);
                  }
            }
        }
        return maxArea;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值