基础

What is a Union-Finding?

  • It is a data structure

  • A data structure

When?

  • 解决图问题

  • use case:图是在动态变化

Why?

  • 代码极其短

  • hit use case 时间复杂度

关注点

  • 两个集合是不是联通

  • 集合==》联通力量

  • 性质:每一个集合都有一个代表

思考方式

  • 集合代表着帮派

  • 集合的代表元素代表帮派老大

API

  • UnionFind() constructor 构造函数O(n), n as number of node

  • union(int a, int b):把a加入b的集合,或者把b加入a的集合

  • int find(a):找到a所在集合的代表元素

时间复杂度

  • Quick Union -- union find

    • find: O(n)

    • union: O(n)

  • Quick Find -- union find

    • find: O(1)

    • union: O(n)

  • Weighted/Ranked/OtherRanked Union Find(Tree Array Based)

    • find: O(log n)

    • union O(log n)

  • Weight Union Find with Path Compression

    • find: O*(1)

    • union: O*(1)

    • where *: O(loglog(n)) > O(1)

How

  • Union - Find用数组实现的数据结构

  • 假设长度是n -> int[] laoda

  • laoda[i] 代表i的老大是谁

  • count:一共有多少个帮派

  • int[] size -> size[i] 代表i所在的帮派有多少

How: Union Find底板(2min!!!)

UF时空复杂度

  • union,find 都是O*(1)

  • constructor: both O(n)

面试里注意点的和基本逻辑

  • 对于find(a):找到的是真老大

  • union(a, b): a,b 要先检查需不需要union,如果老大都一样,就不需要用union了

第一种Union-Find: Quick Union

union(a, b)--> 把a加入b

  • example:

    • laoda: {0, 1, 2},

    • union(2, 1),

    • laoda = {0,1,1}

    • union(1, 0)

    • laoda: {0, 0, 1}

    • 其实0,1,2,都在一个联通分量里面,但是观察老大是分级别的

  • 谁是真老大?

    • 真老大的特点laoda[zhenlaoda] = zhenlaoda

  • quick union:

    • union 一时爽,find的时候要溯源

TC&SC:

  • find: O(n)

  • union: O(n)

第二种Union Find: Quick Find

Find O(1)

example:

  • laoda: {0, 1, 2},

  • union(2, 1),

  • laoda = {0,1,1}

  • union(1, 0)

  • laoda: {0, 0, 1} ==> {0,0,0}

  • 操作上来说,如果要把a的老大改成c,不能只改a,把所有以a为老大的小弟们的老大都改成c(相当于老板跳槽,把他所有学生都带去跳槽)

TC& SC: Find(1), Union(n)

第三种Union- Find, Weight Union Find => Tree

核心思想:

  • union(a,b)刚才是a加入b,or b加入a

  • 现在一定是小的那个,加入大的那个大小: size[i]

  • 是用tree的形式,越靠近tree的顶,越是那个大的

  • example

  • 这里相当于size是weight

第四种Union-Find:Weighted Union FInd with PathCompression

  • Path Compression:路径压缩

  • 路径压缩精髓:苟富贵勿相忘(一个人富贵了,所有帮助给你的人全都浮过)

  • example

其他版本,Pure Recursion Implementation

step1 : function 的定义

  • int fnd(a): 给我一个点a可以找到a所在的帮派

step 2: base case

  • laoda[a] = a return a

step 3: subproblem

  • find(laoda[a]) 这个子问题return的结果的人其实就是zhenlaoda

step 4 recursion rule

  • laoda[a]上面的点已经路径压缩完了

  • 真老大不就是子问题retun的结果了么?

  • laoda[a] = zhenlaoda

  • return zhenlaoda

面试简化版本

多加一个getMaxSetLaoda

add a method findMax()

  • add a method findMax() to the union-find data type so that findMax(i) returns the largest element in the connected component containing i.

  • 对于UF实现上的follow up怎么做?思考徐亚激素哪些新的field,然后改变union(95%) + find(5%)更新他们

Last updated