Leetcode200-岛屿数量,一道经典题目区分BFS和DFS,理解并查集

本文参考岛屿数量

问题描述

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

示例1:

输入:
11110
11010
11000
00000
输出: 1

示例2:

输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

分析:通俗来讲,本题是求给定的二维网格中可以划分几块区域,自然而然想到用并查集来做,也可以看做图来分析,‘1’为顶点,水平或竖直方向上相邻的‘1’为边,然后用BFS或DFS进行遍历,每次遍历完一块区域,岛屿树+1

并查集

按树(集合)的高度,也就是秩(rank)合并, n ∗ i + j n*i+j ni+j 作为元素标识

class UnionFind{
public:
    UnionFind(vector<vector<char>>& grid){
        count=0;
        int m=grid.size();
        int n=grid[0].size();
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]=='1'){
                    parent.push_back(n*i+j);
                    count++;
                }else parent.push_back(-1);
                rank.push_back(0);
            }
        }
    }
    //find元素i所在树的根
    int find(int i){
        if(parent[i]!=i){
            parent[i]=find(parent[i]); //自己不是根,那就看父亲
        }
        return parent[i];
    }
    //合并两元素就是合并这俩元素所在的树,union是C关键字,所以函数名unite
    void unite(int x,int y){
        int rootx=find(x);
        int rooty=find(y);
        if(rootx!=rooty){
            //按rank(也就是树高度)大小合并
            if(rank[rootx]<rank[rooty]){
                swap(rootx,rooty);                
            }
            parent[rooty]=rootx;
            if(rank[rootx]==rank[rooty])  rank[rootx]++;
            count--;
        }
    }
    //count表示树的个数
    int get_count() const{
        return count; 
    }
private:
    vector<int> rank;
    vector<int> parent;
    int count;
};
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int nr=grid.size();        
        if(nr==0) return 0;
        int nc=grid[0].size();
        UnionFind uf(grid);
        for(int r=0;r<nr;r++){
            for(int c=0;c<nc;c++){
                if(grid[r][c]=='1'){
                    grid[r][c]='0';
                    if(r-1>=0&&grid[r-1][c]=='1') uf.unite(r*nc+c,(r-1)*nc+c);
                    if(r+1<nr&&grid[r+1][c]=='1') uf.unite(r*nc+c,(r+1)*nc+c);
                    if(c-1>=0&&grid[r][c-1]=='1') uf.unite(r*nc+c,r*nc+c-1);
                    if(c+1<nc&&grid[r][c+1]=='1') uf.unite(r*nc+c,r*nc+c+1);
                }
            }
        }
        return uf.get_count();
    }
}; 

DFS

这里贴一个DFS的通用模板(伪代码)

void Dfs(Vertex V){
	Visited[V]=True;
	for each W adjacent to V
		if(!Visited[W])
			Dfs(W);
}

直接来看题解

class Solution{
public:
    void dfs(int r,int c){
        int nr=grid.size();
        int nc=grid[0].size();
        grid[r][c]='0';
        if(r-1>=0 && grid[r-1][c]=='1') dfs(r-1,c);
        if(r+1<nr && grid[r+1][c]=='1') dfs(r+1,c);
        if(c-1>=0 && grid[r][c-1]=='1') dfs(r,c-1);
        if(c+1<nc && grid[r][c+1]=='1') dfs(r,c+1);
    }
    int numIslands(vector<vector<char>>& grid){
        int m=grid.size();
        if(m==0) return 0;
        int n=grid[0].size();
        this->grid=grid;
        int num_islands=0;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(this->grid[i][j]=='1'){
                    dfs(i,j);
                    num_islands++;
                }
            }
        }
        return num_islands;
    }
private:
    vector<vector<char>> grid;
};

BFS

无权最短路径算法、Dijkstra 算法 都是 BFS 的经典算法,按层处理节点

class Solution{
public:
    int numIslands(vector<vector<char>>& grid){
        int m=grid.size();
        if(m==0) return 0;
        int n=grid[0].size();
        grid=grid;
        int num_islands=0;
        queue<pair<int,int>> q;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(grid[i][j]=='1'){
                    num_islands++;
                    grid[i][j]='0';
                    q.push({i,j});
                    while(!q.empty()){
                        auto rc=q.front();
                        q.pop();
                        int r=rc.first, c=rc.second;
                        if(r-1>=0 && grid[r-1][c]=='1') {
                            q.push({r-1,c});
                            grid[r-1][c]='0';
                        }
                        if(r+1<m && grid[r+1][c]=='1') {
                            q.push({r+1,c});
                            grid[r+1][c]='0';
                        };
                        if(c-1>=0 && grid[r][c-1]=='1') {
                            q.push({r,c-1});
                            grid[r][c-1]='0';
                        };
                        if(c+1<n && grid[r][c+1]=='1') {
                            q.push({r,c+1});
                            grid[r][c+1]='0';
                        };
                    }
                }
                
            }
        }
        return num_islands;
    }
};

你可能感兴趣的:(dfs,算法,leetcode,bfs,数据结构)