并查集算法讲解:LeetCode 990. 等式方程的可满足性

题目链接:990. 等式方程的可满足性

分析:

题目意思很简单,给你一个字符串数组,根据字符串数组判断其中式子是否可以通过定义变量(既代值)成立。

我看到这个题,当时便分析出这是一道图的连通性的题目,可以使用并查集做。

并查集算法意思很简单,思维很巧妙,设置一个桶数组当做集合,此时每个集合中只有自己本身一个元素(既数组值指向数组下标值)。然后通过给的图的联通条件,不断的将集合归并的算法。我们将每个集合抽象为一个元素,该元素代表着一个集合,而该集合中的其他元素全部指向该元素,从而完成集合的划分。

根据上述分析我们可以很容易得出,我们需要一个输入某个元素返回某个集合的代表元素的方法,而该方法有递归和循环两种方式。

findroot函数代码
//递归
if (ch[c] != c) {
	ch[c]=findroot(ch[c]);
	return ch[c];
}
return c;
//循环
while(ch[c]!=c){
    ch[c]=ch[ch[c]];
    c=ch[c];
}
return c;

此处使用了一个技巧:路径压缩。相信大家很容易发现,当数据过多时,可能某个元素到集合代表元素的中间需要经过多次递归或循环。
而路径压缩就直接将该元素调整指向至集合代表元素,从来大大降低时间复杂度。

而归并的过程更为简单,我们直接将一个集合的代表元素指向另外一个集合的代表元素,如此两个集合便合并为一个集合。

merge函数代码
public void merge(int a, int b) {
			int roota = findroot(a);
			int rootb = findroot(b);
			ch[roota] = rootb;
		}

回到题目,我们先循环字符串数组在==时便将集合归并;在进行一轮循环,当字符串数组!=时,那么我们便判断两元素是否不为同一集合元素,若是,那么返回false;若不是,则继续循环。若第二次循环过程中没有返回false,那么返回true。

完整Java代码
class Solution {
		int[] ch = new int[26];

		public boolean equationsPossible(String[] equations) {
			int len = equations.length;
			for (int i = 0; i < 26; i++)
				ch[i] = i;
			for (String s : equations) {
				if (s.charAt(1) == '=') {
					merge(s.charAt(0) - 'a', s.charAt(3) - 'a');
				}
			}
			for (String s : equations) {
				if (s.charAt(1) == '!') {
					if (findroot(s.charAt(0) - 'a') == findroot(s.charAt(3) - 'a')) {
						return false;
					}
				}
			}
			return true;
		}

		public int findroot(int c) {
			if (ch[c] != c) {
				findroot(ch[c]);
			}
			return c;
		}

		public void merge(int a, int b) {
			int roota = findroot(a);
			int rootb = findroot(b);
			ch[roota] = rootb;
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值