leetcode之路:547. 省份数量

  • 城市和城市连在一块,有多少个省?

  • 一群人里面自己和自己亲戚连在一块,有多少组亲戚?

  • 你俩是不是一个小区的?

  • 他俩是不是有一腿

以上所有问题,抽象,概括为分组问题

老并查集了

这里引用一个知乎大佬的并查集讲解,gang的非常好,我就不赘述了。

并查集讲解

大家主要了解一下并查集的两种优化方法,路径压缩使得所有节点在被查询过后都直接连在根节点上(这样下次查询的时候就可以O(1)查到他属于哪个组),按深度合并分组可以保证树的深度不会过分增长。

这个题可谓练手并查集的好题目
代码如下
class Solution {
private:
    const static int maxn = 200 + 5;
    int fa[maxn], depth[maxn];

    /**
    * 初始化根节点数组,深度数组
    */
    void init(){
        for(int i = 0; i < maxn; i++){
            fa[i] = i;
            depth[i] = 1;
        }
    }

    /**
    * 找到某个节点的根节点(他属于哪一组?)
    */
    int find(int x){
        return (x == fa[x]) ? fa[x] : (fa[x] = find(fa[x]));
    }

    /**
    * 合并两个分组
    */
    void merge(int a, int b){
        int x = find(a), y = find(b);
        if(depth[x] > depth[y])fa[y] = x;
        if(depth[y] > depth[x])fa[x] = y;
        if(depth[x] == depth[y] && x != y){
            fa[x] = y;
            depth[y] ++;
        }
    }
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        init();
        int n = isConnected.size();
        for(int i = 0; i < n; i++){
            for(int j = i + 1; j < n; j++){
                if(i != j && isConnected[i][j]){
                    merge(i, j);
                }
            }
        }
        set<int>ans;
        for(int i = 0; i < n; i++)ans.insert(find(i));//set去一下重,查一下有多少个不同的分组就是多少个省了
        return ans.size();
    }
};
posted @ 2021-01-07 10:18  sheeeeeeep  阅读(120)  评论(0编辑  收藏  举报