赞
踩
【题目描述】
给定一个没有重复值的整型数组 arr,初始时认为 arr 中每一个数各自都是一个单独的集合。
请设计一种叫 UnionFind 的结构,并提供以下两个操作。
1)boolean isSameSet(int a, int b):查询 a 和 b 这两个数是否属于一个集合。
2)void union(int a, int b):把 a 所在的集合与 b 所在的集合合并在一起,原本两个集合各自的元素以后都算作同一个集合。
【要求】
如果调用 isSameSet 和 union 的总次数逼近或超过 O(N),请做到单次调用 isSameSet 或 union
方法的平均时间复杂度为 O(1)。
private static class Node<V> {
private V value;
public Node(V value) {
this.value = value;
}
}
public static class UnionFindSet<V> { /** * V -> Node 关系映射 */ private HashMap<V, Node<V>> elementMap; /** * 存储Node以及其集合根结点 */ private HashMap<Node<V>, Node<V>> fatherMap; /** * 存储集合根结点元素 以及其集合元素数量 */ private HashMap<Node<V>, Integer> sizeMap; public UnionFindSet(List<V> list) { elementMap = new HashMap<>(); fatherMap = new HashMap<>(); sizeMap = new HashMap<>(); makeSet(list); } private void makeSet(List<V> list) { for (V v : list) { Node node = new Node(v); elementMap.put(v, node); fatherMap.put(node, node); sizeMap.put(node, 1); } } /** * 递归查找一个Node对应的头结点 * * @return */ private Node findHead(Node node) { if (node == null) { return null; } Node father = fatherMap.get(node); if (father != node) { father = findHead(father); } //将当前结点直接挂接到头结点上,降低层级 fatherMap.put(node, father); return father; } /** * 查找两个结点是否处于同一集合 * * @param a 结点a * @param b 结点b * @return */ public boolean isSameSet(V a, V b) { if (elementMap.containsKey(a) && elementMap.containsKey(b)) { return findHead(elementMap.get(a)) == findHead(elementMap.get(b)); } return false; } /** * 合并两个集合 * * @param a * @param b */ public void union(V a, V b) { if (elementMap.containsKey(a) && elementMap.containsKey(b)) { Node aHead = findHead(elementMap.get(a)); Node bHead = findHead(elementMap.get(b)); //两者头结点相同,不需要合并 if (aHead == bHead) { return; } int aSize = sizeMap.get(aHead); int bSize = sizeMap.get(bHead); //将结点数少的挂在结点数多的上面 if (aSize <= bSize) { fatherMap.put(aHead, bHead); sizeMap.put(bHead, aSize + bSize); } else { fatherMap.put(bHead, aHead); sizeMap.put(aHead, aSize + bSize); } } } }
public static void main(String[] args) { int[] arr = {1, 2, 3, 4}; List<Integer> list = new ArrayList<>(); for (int i : arr) { list.add(i); } UnionFindSet set = new UnionFindSet(list); set.union(1, 3); set.union(2, 4); boolean sameSet1 = set.isSameSet(2, 3); boolean sameSet2 = set.isSameSet(2, 4); System.out.println(sameSet1); System.out.println(sameSet2); }
false
true
如果以上文章对您有一点点帮助,希望您不要吝啬的点个赞加个关注,您每一次小小的举动都是我坚持写作的不懈动力!ღ( ´・ᴗ・` )
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。