并查集(Union-Find)用来合并集合和查找集合,但不支持分割集合。
从集合中选择一个元素代表该集合,称该元素为该集合的代表元。
集合中的所有元素被组织成以代表元为根的树形结构。并且使用双亲表示法表示该树。
常用操作:
Node findRoot(x) { node = x; while (node.getParent() >= 0) node = node.getParent(); return node; }
boolean isInOneSet(x, y) { return findRoot(x) == findRoot(y); }
因为 findRoot()
方法的时间复杂度与树的深度是成正比,所以在合并集合时,应该尽量减少合并后的树的深度,这个过程叫路径压缩。
因为在树的双亲表示法中,根节点的父索引是一个负值,所以可以使用这该值表示该树的深度。在合并时,将较浅的树合并到较深的树。
union(x, y) { rootX = findRoot(x); rootY = findRoot(y); if (rootX == rootY) return; depthX = -1 * rootX.getParent(); depthY = -1 * rootY.getParent(); if (depthX == depthY) { rootY.setParent(rootX); rootX.setParent(rootX.getParent() - 1); } else if (depthX < depthY) { rootX.setParent(rootY); } else { rootY.setParent(rootX); } }
题目名称:
等式方程的可满足性
原题地址:
题目描述:
给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。
Python 实现:
# coding: utf8 class Node(object): def __init__(self): self.parent = -1 class UnionFindSet(object): def __init__(self): self._nodes = [Node() for _ in range(27)] def find_root(self, x): temp = x while self._nodes[temp].parent >= 0: temp = self._nodes[temp].parent return temp def merge(self, x, y): si = self.find_root(x) sj = self.find_root(y) if si == sj: return node_i = self._nodes[si] depth_i = -1 * node_i.parent node_j = self._nodes[sj] depth_j = -1 * node_j.parent if depth_i >= depth_j: self._nodes[sj].parent = si self._nodes[si].parent = -1 * max(depth_i, depth_j+1) else: self._nodes[si].parent = sj self._nodes[sj].parent = -1 * max(depth_j, depth_i+1) class Solution(object): def equationsPossible(self, equations): """ :type equations: List[str] :rtype: bool """ ufs = UnionFindSet() for equation in equations: if equation[1] != "=": continue ufs.merge( ord(equation[0])-ord("a"), ord(equation[3])-ord("a")) for equation in equations: if equation[1] != "!": continue if ufs.find_root(ord(equation[0])-ord("a")) == \ ufs.find_root(ord(equation[3])-ord("a")): return False return True if __name__ == "__main__": equations = ["a==b", "b==c", "a==c", "e==f", "a!=c"] solution = Solution() print(solution.equationsPossible(equations))