LeetCode-并查集

1. 547. 省份数量

经典题目,找无关联点集的数量
merge并,find查,add添加节点,主要就是三个函数

class unionFind{
public:
    unordered_map<int,int> fathers;
    int sum=0;
    void add(int x){    //添加节点
        if(!fathers.count(x)){
            fathers[x]=x;
            sum++;
        }
    }
    int find(int x){    //找根结点
        int root=x;
        while(root!=fathers[root]){
            root=fathers[root];
        }
        while(x!=root){
            int temp=fathers[x];
            fathers[x]=root;
            x=temp;
        }
        return root;
    }
    bool is_connected(int x,int y){ //判断是否有共同根结点
        return find(x) == find(y);
    }
    void merge(int x,int y){    //合并两个点集
        int rootx=find(x);
        int rooty=find(y);
        if(rootx!=rooty){
            fathers[rooty]=rootx;
            sum--;
        }
    }
};
class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
        unionFind uf;
        for(int i=0;i<isConnected.size();i++){	遍历城市
            uf.add(i);
            for(int j=0;j<i;j++){
                if(isConnected[i][j]){
                    uf.merge(i,j);
                }
            }
        }
        return uf.sum;
    }
};

2. 959. 由斜杠划分区域

真吉尔爽
把每个小方格划分成了四个区域,每个方格索引为n*i+j
每个小三角之索引为方格索引乘4+j
每个小三角看作一个点,当 / 时,连接1,2和0,3,\ 时连接0,1和2,3,为空格时把连接01,12,23,即四个点都连通
另,每个方格1和它右面方格的3,2和下面方格的0无论如何都是联通的,所以直接连接这几个点(,每次与右、下连接,注意不要越界)
最后连通分量的个数即为答案,所以用并查集做
在这里插入图片描述

class Solution {
public:
    unordered_map<int,int> father;
    int count;
    int find(int a){
        int root=a;
        while(father[root]!=root){
            root=father[root];
        }
        while(a!=root){
            int t=father[a];
            father[a]=root;
            a=t;
        }
        return root;
    }
    void merge(int a,int b){
        int roota=find(a);
        int rootb=find(b);
        if(roota!=rootb){
            father[roota]=rootb;
            count--;
        }
    }
    int regionsBySlashes(vector<string>& grid) {
        int n=grid.size();
        count=n*n*4;
        for(int i=0;i<n*n*4;i++){
            father[i]=i;
        }
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                int index=n*i+j;
                if(i<n-1){	//与下方合并
                    int bottom=index+n;
                    merge(index*4+2,bottom*4);
                }
                if(j<n-1){	//与右方合并
                    int right=index+1;
                    merge(index*4+1,right*4+3);
                }
                if(grid[i][j]=='\\'){
                    merge(index*4,index*4+1);
                    merge(index*4+2,index*4+3);
                }
                else if(grid[i][j]=='/'){
                    merge(index*4+1,index*4+2);
                    merge(index*4,index*4+3);
                }
                else{
                    merge(index*4,index*4+1);
                    merge(index*4+1,index*4+2);
                    merge(index*4+2,index*4+3);
                }
            }
        }
        return count;
    }
};

3. 990. 等式方程的可满足性

==具有连通性,先把所有相等的点连通起来,并可记录下互不相等的点
然后遍历互不相等的点,如果本应互不相等的点有连通性(即有式子表明他俩相等)返回false
用c-‘a’表示点的索引,并查集流啤

class Solution {
public:
    vector<int> father;
    int find(int a){
        int root=a;
        while(root!=father[root]){
            root=father[root];
        }
        while(a!=root){
            int t=father[a];
            father[a]=root;
            a=t;
        }
        return root;
    }
    void merge(int a,int b){
        int roota=find(a);
        int rootb=find(b);
        if(roota!=rootb){
            father[roota]=rootb;
        }
    }
    bool equationsPossible(vector<string>& equations) {
        father.resize(26);
        for(int i=0;i<26;i++){
            father[i]=i;
        }
        vector<pair<int,int>> vec;
        for(string str:equations){
            int first=str[0]-'a';
            int second=str[3]-'a';
            if(str[1]=='='){
                merge(first,second);
            }
            else{
                vec.push_back(make_pair(first,second));
            }
        }
        for(auto p:vec){
            if(find(p.first)==find(p.second)){
                return false;
            }
        }
        return true;
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值