[英]Creating dictionaries of Friends that know other Friends in python
在任何一群人中都有很多對朋友。 假設共享一個朋友的兩個人本身就是朋友。 (是的,這是現實生活中的不切實際的假設,不過還是讓我們做吧)。 換句話說,如果人A和B是朋友,而B是與C的朋友,那么A和C也必須是朋友。 使用此規則,只要我們對某群人中的友誼有所了解,就可以將任何人划分為多個友誼圈。
編寫一個帶有兩個參數的函數networks()。 第一個參數是組中的人數,第二個參數是定義朋友的元組對象列表。 假設通過數字0到n-1來識別人。 例如,元組(0,2)表示人0是與人2的朋友。此功能應將人的分區打印到友誼圈中。 下面顯示了該函數的幾個示例運行:
>>>networks(5,[(0,1),(1,2),(3,4)])#execute
社交網絡0為{0,1,2}
社交網絡1為{3,4}
老實說,我對如何啟動該程序非常迷失,任何提示將不勝感激。
可用於解決此問題的一種有效數據結構是disjoint set
,也稱為union-find
結構。 前一段時間,我寫了另一個答案 。
結構如下:
class UnionFind:
def __init__(self):
self.rank = {}
self.parent = {}
def find(self, element):
if element not in self.parent: # leader elements are not in `parent` dict
return element
leader = self.find(self.parent[element]) # search recursively
self.parent[element] = leader # compress path by saving leader as parent
return leader
def union(self, leader1, leader2):
rank1 = self.rank.get(leader1,1)
rank2 = self.rank.get(leader2,1)
if rank1 > rank2: # union by rank
self.parent[leader2] = leader1
elif rank2 > rank1:
self.parent[leader1] = leader2
else: # ranks are equal
self.parent[leader2] = leader1 # favor leader1 arbitrarily
self.rank[leader1] = rank1+1 # increment rank
這是解決問題的方法:
def networks(num_people, friends):
# first process the "friends" list to build disjoint sets
network = UnionFind()
for a, b in friends:
network.union(network.find(a), network.find(b))
# now assemble the groups (indexed by an arbitrarily chosen leader)
groups = defaultdict(list)
for person in range(num_people):
groups[network.find(person)].append(person)
# now print out the groups (you can call `set` on `g` if you want brackets)
for i, g in enumerate(groups.values()):
print("Social network {} is {}".format(i, g))
這是一個基於圖中連接組件的解決方案(由@Blckknght建議):
def make_friends_graph(people, friends):
# graph of friends (adjacency lists representation)
G = {person: [] for person in people} # person -> direct friends list
for a, b in friends:
G[a].append(b) # a is friends with b
G[b].append(a) # b is friends with a
return G
def networks(num_people, friends):
direct_friends = make_friends_graph(range(num_people), friends)
seen = set() # already seen people
# person's friendship circle is a person themselves
# plus friendship circles of all their direct friends
# minus already seen people
def friendship_circle(person): # connected component
seen.add(person)
yield person
for friend in direct_friends[person]:
if friend not in seen:
yield from friendship_circle(friend)
# on Python <3.3
# for indirect_friend in friendship_circle(friend):
# yield indirect_friend
# group people into friendship circles
circles = (friendship_circle(person) for person in range(num_people)
if person not in seen)
# print friendship circles
for i, circle in enumerate(circles):
print("Social network %d is {%s}" % (i, ",".join(map(str, circle))))
例:
networks(5, [(0,1),(1,2),(3,4)])
# -> Social network 0 is {0,1,2}
# -> Social network 1 is {3,4}
def networks(n,lst):
groups= []
for i in range(n)
groups.append({i})
for pair in lst:
union = groups[pair[0]]|groups[pair[1]]
for p in union:
groups[p]=union
sets= set()
for g in groups:
sets.add(tuple(g))
i=0
for s in sets:
print("network",i,"is",set(s))
i+=1
如果有人在乎,這就是我一直在尋找的東西。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.