【问题标题】:How to form an unique collection with one element taken from each array?如何使用从每个数组中提取的一个元素来形成一个唯一的集合?
【发布时间】:2015-03-12 22:21:10
【问题描述】:

假设我有 3 个整数数组:{1,2,3}, {2,3}, {1}

我必须从每个数组中只取一个元素,以形成一个所有数字都是唯一的新数组。在本例中,正确答案是:{2,3,1} and {3,2,1}。 (因为我必须从第三个数组中取出一个元素,并且我希望所有数字都是唯一的,所以我绝不能从第一个数组中取出数字 1。)

我做了什么:

for a in array1:
    for b in array2:
        for c in array3:
            if a != b and a != c and b != c:
                AddAnswer(a,b,c)

这是蛮力,虽然有效,但不能很好地扩展。如果现在我们要处理 20 个数组而不是 3 个呢?我认为编写 20 个嵌套的 for 循环并不好。有没有聪明的方法来做到这一点?

【问题讨论】:

  • 您需要所有可能的集合还是只需要一个?
  • 所有可能的集合,谢谢。
  • 当您指定一种语言时,这样就容易多了。 :)
  • 一种选择是执行递归函数,当您排除值列表时,该函数会列出集合列表中的所有解决方案:如果有一个集合,则只需返回剩余值的列表(在一个单例集),否则你循环第一个集的剩余值,然后递归地将当前值添加到排除列表。

标签: python arrays algorithm


【解决方案1】:

怎么样:

import itertools

arrs = [[1,2,3], [2,3], [1]]

for x in itertools.product(*arrs):
    if len(set(x)) < len(arrs): continue
    AddAnswer(x)

AddAnswer(x) 被调用两次,使用元组:

(2, 3, 1) (3, 2, 1)

【讨论】:

  • 您可以通过将其更改为if len(set(x)) &lt; len(arrs)来使其更通用
  • 对我自己的回答的强制性说明:这仍然是蛮力。
  • 套装也可以吗?
  • @allcaps,你的意思是,例如:arrs = [set([1,2,3]), set([2,3]), set([1])] -- 如果是,那么是的。
【解决方案2】:

您可以将其视为在二分图中找到匹配项。

您试图从每个集合中选择一个元素,但不允许选择相同的元素两次,因此您正在尝试将集合与数字匹配。

您可以使用matching function in the graph library NetworkX 有效地执行此操作。

Python 示例代码:

import networkx as nx

A=[ [1,2,3],  [2,3],  [1] ]

numbers = set()
for s in A:
    for n in s:
        numbers.add(n)

B = nx.Graph()
for n in numbers:
    B.add_node('%d'%n,bipartite=1)
for i,s in enumerate(A):
    set_name = 's%d'%i
    B.add_node(set_name,bipartite=0)
    for n in s:
        B.add_edge(set_name,n)

matching = nx.maximal_matching(B)
if len(matching) != len(A):
    print 'No complete matching'
else:
    for number,set_name in matching:
        print 'choose',number,'from',set_name

这是查找单个匹配项的一种简单有效的方法。

如果您想枚举所有匹配项,您可能希望阅读: Algorithms for Enumerating All Perfect, Maximum and Maximal Matchings in Bipartite Graphs by Takeaki UNO 每次匹配的复杂度为 O(V)。

【讨论】:

  • 非常感谢您的见解。我从来没有这样想过!
【解决方案3】:

递归解决方案(未测试):

def max_sets(list_of_sets, excluded=[]):
    if not list_of_sets:
        return [set()]
    else:
        res = []
        for x in list_of_sets[0]:
            if x not in excluded:
                for candidate in max_sets(list_of_sets[1:], exclude+[x]):
                    candidate.add(x)
                    res.append(candidate)
        return res

(您可能可以省去set,但不清楚它是否在问题中......)

【讨论】:

    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多