并查集是用于解决动态连通性类问题的一种数据结构
涉及两个函数
union用于将图的两个节点连接
连通的节点被称为一个组
Quick-Find实现
def find(a,b):
if arr[a] == arr[b]:
print("YES")
else:
print("NO")
def union(a,b):
for i in range(arrsize):
if i == b:
continue
if(arr[i] == arr[a]):
arr[i] = arr[b]
arr[a] = arr[b]
Quick-Union实现
上面的Quick-find实现在规模增大时,会面临性能问题,其主要来源是union操作需要遍历数组,为了改善性能,需要避免执行union操作时遍历数组,Quick-Union实现达到了这一目的
def root(a):
i = a
while(arr[i] != i):
i = arr[i]
return i
def find(a,b):
if (root(a) == root(b)):
print("YES")
else:
print("NO")
def union(a,b):
arr[root(a)] = root(b)
Quick-Union实现中,最坏情况的时间复杂度为O(N^2),最坏情况即树的高度最高,等于元素数量总和,要进一步改善Quick-Union的性能,需要限制树的最大高度
def root(a):
i = a
while(arr[i] != i):
i = arr[i]
return i
def find(a,b):
if (root(a) == root(b)):
print("YES")
else:
print("NO")
def union(a,b):
if sz[root(a)] < sz[root(b)]:
sz[root(b)] += sz[root(a)]
arr[root(a)] = root(b)
else:
sz[root(a)] += sz[root(b)]
arr[root(b)] = root(a)
def root(a):
i = a
while(arr[i] != i):
i = arr[i]
return i
def find(a,b):
if (root(a) == root(b)):
arr[a] = arr[root(a)]
print("YES")
else:
print("NO")
def union(a,b):
if sz[root(a)] < sz[root(b)]:
sz[root(b)] += sz[root(a)]
arr[root(a)] = root(b)
else:
sz[root(a)] += sz[root(b)]
arr[root(b)] = root(a)
Social network connectivity. Given a social network containing N members and a log file containing M timestamps at which times pairs of members formed friendships, design an algorithm to determine the earliest time at which all members are connected (i.e., every member is a friend of a friend of a friend ... of a friend). Assume that the log file is sorted by timestamp and that friendship is an equivalence relation. The running time of your algorithm should be MlogN or better and use extra space proportional to N.
宝典P231:假如已知n个人和m对好友关系(存于数组r),若两个人是直接或间接的好友,则认为他们属于同一个朋友圈,请写程序求出这n个人里一共有多少个朋友圈,并分析代码的时间、空间复杂度
friends = []
size = []
def root(a):
i = a
while(friends[i] != i):
i = friends[i]
return i
def find(a, b):
if(root(a) == root(b)):
friends[a] = friends[friends[a]]
return True
return False
def union(a, b):
i = root(a)
j = root(b)
if(size[i] < size[j]):
size[j] += size[i]
friends[i] = j
else:
size[i] += size[j]
friends[j] = i
def cntset():
setcnt = 0
for i in range(peoplecnt):
if(friends[i] == i):
setcnt += 1
return setcnt
peoplecnt = int(raw_input("Input Number of people:"))
for i in range(peoplecnt):
friends.append(i)
size.append(1)
while True:
a = int(raw_input("Input a:"))
b = int(raw_input("Input b:"))
if(a == -1 | b == -1):
break;
else:
union(a,b)
print(cntset())
Union-find with specific canonical element. Add a method find() to the union-find data type so that find(i) returns the largest element in the connected component containing i. The operations, union(), connected(), and find() should all take logarithmic time or better.
For example, if one of the connected components is {1,2,6,9}, then the find() method should return 9 for each of the four elements in the connected components.
Successor with delete. Given a set of N integers $S={0,1,...,N−1} $and a sequence of requests of the following form:
Remove $x$ from $S$
Find the successor of$ x$: the smallest $y$ in $S$ such that $y≥x$.
design a data type so that all operations (except construction) should take logarithmic time or better.
arr = [0,1,2,3,4,5,6,7,8,9]
sz = [1,1,1,1,1,1,1,1,1,1]
maxe = [i for i in arr]
def root(a):
i = a
while(arr[i] != i):
i = arr[i]
return i
def find(a,b):
if (root(a) == root(b)):
arr[a] = arr[root(a)]
print("YES")
else:
print("NO")
def union(a,b):
i = root(a)
j = root(b)
if sz[i] < sz[j]:
sz[j] += sz[i]
maxe[j] = max(maxe[j], maxe[i])
arr[i] = j
else:
sz[i] += sz[j]
maxe[i] = max(maxe[j], maxe[i])
arr[j] = i
print("Array size 10, index from 0~9")
while 1:
x = int(raw_input("input index to delete"))
if x == 9:
print("9 is max in the sequence, no successor")
else:
union(x, x+1)
print("successor of " + str(x) + " is " + str(maxe[root(x)]))
Written with StackEdit.