Leetcode.200&Leetcode.547:广度优先遍历/深度优先遍历

Leetcode200.岛屿数量

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。

示例1:

输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1

示例2:

输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3

方法一:广度优先遍历

  1. 按行列的顺序依次遍历二维数组,每遍历到一个1,说明涉足到一片新陆地,答案ans+1。
  2. 对当前探索到的陆地进行广度优先搜索,建立队列,将刚涉足的1坐标入队,探索该坐标块上下左右(套用模板,双数组建立四周坐标,注意判断是否越界),将满足条件且值为1的陆地坐标块入队,同时设置该坐标块为0,避免后续重复遍历。
  3. 探索完该坐标块,将坐标块出队 ,对下一个队首元素进行广度优先搜索,转步骤2,直至队列为空。
  4. 队列为空说明探索完了一整片大陆,转步骤1,探索新的大陆。

代码

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int Xi[4]={0, 1, 0, -1};
        int Yi[4]={1, 0, -1, 0};
        int height = grid.size();
        if(height==0) return 0;
        int width = grid[0].size();
        int ans = 0;
        queue<pair<int,int>> q;
        for(int i=0;i<height;i++){
            for(int j=0;j<width;j++){
                if(grid[i][j]=='1'){
                    grid[i][j]='0';
                    ans+=1;
                    q.emplace(i,j);
                    while(!q.empty()){
                        int x = q.front().first;
                        int y = q.front().second;
                        for(int t=0;t<4;t++){
                            int xi = x+Xi[t];
                            int yi = y+Yi[t];
                            if(xi>=0&&xi<height&&yi>=0&&yi<width&&grid[xi][yi]=='1'){
                                q.emplace(xi,yi);
                                grid[xi][yi] = '0';
                            }
                        }
                        q.pop();
                    }
                }
            }
        }
        return ans;
    }
};

方法二:深度优先遍历(暂时一知半解勉强可以做出来,理解还不透彻,解析待补充)
代码

在这里插入代码片class Solution {
public:
    void dfs(vector<vector<char>>& grid,int x,int y){
        int height = grid.size();
        int width = grid[0].size();
        grid[x][y] = '0';
        int dx[4] = {1,-1,0,0};
        int dy[4] = {0,0,-1,1};
        for(int i=0;i<4;i++){
            int xi = x+dx[i],yi = y+dy[i];
            if(xi>=0&&xi<height&&yi>=0&&yi<width&&grid[xi][yi]=='1'){
                dfs(grid,xi,yi);
            }
        }
    }
    int numIslands(vector<vector<char>>& grid) {
        int height = grid.size();
        if(height==0) return 0;
        int width = grid[0].size();
        int ans = 0;
        for(int i=0;i<width;i++){
            for(int j=0;j<height;j++){
                if(grid[j][i]=='1'){
                    ans+=1;
                    dfs(grid,j,i);
                }
            }
        }
        return ans;
    }
};

Leetcode547.省份数量

示例1:
Leetcode.200&Leetcode.547:广度优先遍历/深度优先遍历_第1张图片

输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2

示例2:
Leetcode.200&Leetcode.547:广度优先遍历/深度优先遍历_第2张图片

输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出:3

方法一:广度优先遍历

  1. 设置标记数组flag,用于记录城市是否被搜索过,初始值均设为0。
  2. 遍历flag探索每一个城市,每遍历到一个1,说明探索到一个新省份的第一个城市,答案ans+1。
  3. 对当前探索到的省份进行广度优先搜索,建立队列,将刚涉足的城市下标入队,访问二维数组isConnected[][]中以该城市为出发点的城市(如判断与城市3相邻的城市,遍历t访问isConnected[3][t]即可),将满足条件(isConnected中值为1)且flag值为1的城市下标入队,同时设置该flag数组中该下标位置为0,避免后续重复访问。
  4. 探索完该城市,将城市坐标出队 ,对下一个队首元素(即周边城市)进行广度优先搜索,转步骤2,直至队列为空。
  5. 队列为空说明探索完了一整个省份,转步骤1,探索新省份的第一个城市。

代码

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        int nums = isConnected.size();
        int ans = 0;
        int flag[nums];
        memset(flag,0,sizeof(flag));
        queue<int> q;
        for(int i=0;i<nums;i++){
            if(flag[i]==0){
                ans+=1;
                flag[i]=1;
                q.push(i);
                while(!q.empty()){
                    int j = q.front();
                    q.pop();
                    for(int t=0;t<nums;t++){
                        if(isConnected[j][t]==1&&flag[t]==0){
                            q.push(t);
                            flag[t]=1;
                        }
                    }
                }
            }
        }
        return ans;
    }
};

方法二:深度优先遍历(暂时一知半解勉强可以做出来,理解还不透彻,解析待补充)
代码

class Solution {
public:
    int flag[201]={0};//全局数组,可以这样赋初值为0,局部数组则需要memset函数
    void dfs(vector<vector<int>>& isConnected,int i){
        int nums = isConnected.size();
        for(int t=0;t<nums;t++){
            if(flag[t]==0&&isConnected[i][t]==1){
                flag[t]=1;
                dfs(isConnected,t);
            }
        }
    }
    int findCircleNum(vector<vector<int>>& isConnected) {
        int nums = isConnected.size();
        if(nums==0) return 0;
        int ans = 0;
        for(int i=0;i<nums;i++){
            if(flag[i]==0){
                flag[i] = 1;
                ans+=1;
                dfs(isConnected,i);
            }
        }
        return ans;
    }
};

你可能感兴趣的:(算法,数据结构,深度优先,宽度优先,c++)