【问题标题】:Best algorithm to solve this array problem?解决这个数组问题的最佳算法?
【发布时间】:2022-01-22 09:15:09
【问题描述】:

如果输入,我有一个这样的列表列表

[[2,1], [1,3], [4,5], [6,8], [4,7]]

我怎样才能找到一个/最大的子集,使得根本没有重复/共享元素?

对于这个例子,答案是

[2,1], [4,5], [6,8] 

[1,3], [6,8], [4,7] 

但是一个无效的答案会是

[2,1],[1,3],[4,5] 

因为 1 在这里出现了两次。

我目前的方法是一种递归方法,它使用的想法是要么选择第一个元素,要么在构建子集时不选择第一个元素,但这种方法似乎太慢了。

我所拥有的:目前它只返回最大子集的大小而不是实际子集的大小,但是一旦大小起作用,应该很容易得到它

def disjointSets(allSets):
    maxCount = 0
    used = set()
    def findDisjoint(currCount, arr):
        nonlocal maxCount
        if not arr:
            maxCount = max(maxCount, currCount)
            return
        elif arr[0][0] in used or arr[0][1] in used:
            findDisjoint(currCount, arr[1:])
            return
        else:
            used.add(arr[0][0])
            used.add(arr[0][1])
            findDisjoint(currCount + 1, arr[1:])
            used.clear()
            findDisjoint(currCount, arr[1:])
        return
    findDisjoint(0, allSets)
    return maxCount

【问题讨论】:

标签: python arrays list algorithm


【解决方案1】:

这里有一个图——数字是顶点,数字对是边。

您的问题是找到最大的独立边集(不共享顶点的边)。

这通常被称为最大匹配,这是一个众所周知的问题,具有众所周知的解决方案。 Blossom algorithm 是保证找到最佳答案的最简单实用的方法。

【讨论】:

  • 谢谢!我研究了一下,现在说得通了。假设我想扩展问题并使数组的每个元素现在都有 3 个元素,例如 [[1,2,3]、[4,5,6] 等]。用类似的方法还有可能吗?
  • 我不知道有一种类似的方法适用于三元组
【解决方案2】:

正如@MattTimmermans 所说,您在这里拥有的是一个无向图,其中每个数字都是一个节点,每一对都是一条边。匹配是一组不共享节点的边,您的工作是找到最大匹配,即包含最大边数的匹配。

有一个名为 networkx 的 Python 包处理网络,尤其是图形。其中有一个名为 max_weight_matching 的方法,它实现了 Edmonds 的开花算法。

在你的例子中:

import networkx as nx
G = nx.Graph()
G.add_edges_from([[2,1], [1,3], [4,5], [6,8], [4,7]])
out = nx.max_weight_matching(G)

输出:

{(8, 6), (4, 7), (1, 3)}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    • 2021-06-19
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多