并查集(Union-find set)

它是一种维护集合的数据结构,它的名字"并" "查" "集" 。即 union / find / set。 并查集产生的每个集合都是一棵树(tree) 。基本操作:
1.合并两个集合union。
2.判断两个元素是否在一个集合中find。

实现:
利用一个数组int father[N];其中父节点自身也在1-N之中 
用来记录父节点:即father[i]表示的i节点的父亲节点。当a和b的father[a]==father[b]时,a和b才是联通的。

初始化:

void init(int fa[], int n){
	for(int i = 0; i < n; i ++){
		fa[i] = i;//令它成为-1也可以 
	}
}

find操作,查找并返回包含元素x的树的根:

int findFather(int x){
	while(x != father[x]){// 如果是-1则此处为father[x] >= 0 
		x = father[x];//获得父亲节点 
	}
	return x;
}

合并两个不相交的子集合 :

void Union(int fa[], int root1, int root2){
	int f1 = findFather(root1);
	int f2 = findFather(root2);
	
	if(f1 != f2){
		//即表示f2的父亲节点是father[f1] 
		fa[f1] = f2;
	}
} 

利用并查集解决问题:leetcode 990. 等式方程的可满足性

题目描述:

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。 

分析:先根据等式条件建立起连接关系(并查集),然后在不等条件下,如果两个变量名对应树的root的index是相同的,即和之前两变量名在等式条件的关系冲突,即返回false。

class Solution {
public:

    vector<int> parent;
    int find(int x){
        while(x != parent[x]){
            x = parent[x];//一层一层的往上找
        }
        return x;
    }
  
    bool equationsPossible(vector<string>& equations) {

        parent = vector<int>(26);
        //初始化
        for(int i = 0; i < 26; i ++){
            parent[i] = i;
        }
        for(const string& s : equations){
            if(s[1] == '='){//==
                int idx1 = find(s[0] - 'a');
                int idx2 = find(s[3] - 'a');
                if(idx1 != idx2){
                    parent[idx2] = idx1;
                }
            }
        }

        for(const string& s : equations){
            if(s[1] == '!'){//!=
                int idx1 = find(s[0] - 'a');
                int idx2 = find(s[3] - 'a');
                if(idx1 == idx2){
                    return false;
                }
            }
        }
        return true;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值