【问题标题】:Creating dictionaries of Friends that know other Friends in python在python中创建认识其他朋友的朋友的字典
【发布时间】:2013-03-11 05:39:10
【问题描述】:

在任何一群人中,都有很多对朋友。假设分享朋友的两个人本身就是朋友。 (是的,这在现实生活中是一个不切实际的假设,但让我们仍然这样做)。换句话说,如果 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}

老实说,我对如何启动这个程序很迷茫,任何提示都将不胜感激。

【问题讨论】:

  • 你想找到图中的连通分量,可以使用union find算法快速找到。

标签: python python-3.x social-networking dictionary


【解决方案1】:

一个可以用来解决这个问题的有效数据结构是disjoint set,也称为union-find 结构。不久前我为another answer写了一篇。

结构如下:

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))

【讨论】:

  • 这是一个很棒的解决方案,而且效果很好,但是我的教授不允许我们使用数据结构,除非我们创建了它们。必须有一个更简单的解决方案,而不使用外部数据结构。谢谢你!这是一个非常精明的解决方案。
  • 好吧,您可以编写自己的 UnionFind 实现,或者您可以找到其他算法。在connected components 的 Wiki 页面上有一个相当简单的描述。不过,您可能需要将您的朋友列表转换为邻接列表。
【解决方案2】:
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

如果有人关心,这就是我一直在寻找的。​​p>

【讨论】:

    【解决方案3】:

    这里有一个基于connected components in a graph的解决方案(@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}
    

    【讨论】:

      猜你喜欢
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多