You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何还原N choose 2组合?求更优解法或代码优化方案

问题:从两两配对集合还原原始完整集合

问题背景

我有一组包含多个N选2组合结果的配对集合,需要将这些组合还原为原始的完整集合。

示例输入

inputs = {
    ('id1', 'id2'), ('id1', 'id3'), ('id1', 'id4'),
    ('id2', 'id3'), ('id2', 'id4'),
    ('id3', 'id4'), ('id3', 'id5'),
    ('id4', 'id5'),
    ('id5', 'id6'),
}

示例输出

recombinations = [
    ('id1', 'id2', 'id3', 'id4'),
    ('id3', 'id4', 'id5'),
    ('id5', 'id6'),
]

现有暴力实现代码

我已经用暴力法实现了功能,代码如下:

import itertools

ids = list(sorted( {i for i in itertools.chain(*inputs)} ))

excludes = set()
recombinations = {tuple(i) for i in map(sorted, inputs)}

for i in range(3, len(ids)+1):
    for subset in itertools.combinations(ids, i):
        for j in range(i-1, len(subset)):
            combs = set(itertools.combinations(subset, j))
            if all(tup in recombinations for tup in combs):
                recombinations.add(subset)
                excludes = excludes.union(combs)

for tup in excludes:
    recombinations.remove(tup)

print(recombinations)

运行结果

{('id1', 'id2', 'id3', 'id4'), ('id3', 'id4', 'id5'), ('id5', 'id6')}

优化方案:基于图论的极大团求解

暴力法时间复杂度为O(2^n),元素数量较多时性能极差。实际上这个问题等价于寻找无向图中的所有极大团:每个配对是图的一条边,每个原始完整集合就是一个无法再扩展的完全子图(极大团)。

可以使用Bron–Kerbosch算法高效求解,这是专门用于寻找无向图所有极大团的经典算法,实际运行效率远优于暴力枚举。

优化后代码实现

from itertools import combinations

def bronkkerbosch(R, P, X, graph, cliques):
    if not P and not X:
        cliques.add(tuple(sorted(R)))
        return
    for v in list(P):
        bronkkerbosch(R | {v}, P & graph[v], X & graph[v], graph, cliques)
        P.remove(v)
        X.add(v)

def recover_sets(input_pairs):
    # 构建邻接表形式的图
    graph = {}
    for u, v in input_pairs:
        if u not in graph:
            graph[u] = set()
        graph[u].add(v)
        if v not in graph:
            graph[v] = set()
        graph[v].add(u)
    
    # 初始化所有节点集合
    all_nodes = set(graph.keys())
    cliques = set()
    
    # 运行Bron–Kerbosch算法找所有极大团
    bronkkerbosch(set(), all_nodes, set(), graph, cliques)
    
    # 按长度降序、字典序排序,对齐示例输出格式
    return sorted(cliques, key=lambda x: (-len(x), x))

# 测试
inputs = {
    ('id1', 'id2'), ('id1', 'id3'), ('id1', 'id4'),
    ('id2', 'id3'), ('id2', 'id4'),
    ('id3', 'id4'), ('id3', 'id5'),
    ('id4', 'id5'),
    ('id5', 'id6'),
}

recombinations = recover_sets(inputs)
print(recombinations)

运行结果

[('id1', 'id2', 'id3', 'id4'), ('id3', 'id4', 'id5'), ('id5', 'id6')]

方案优势

  • 效率提升:Bron–Kerbosch算法在实际场景中性能远超暴力枚举,节点数量越多优势越明显。
  • 逻辑清晰:直接对应问题的图论本质,代码可读性和可维护性更强。
  • 结果准确:能精准找出所有极大团,不会出现遗漏或错误。

内容的提问来源于stack exchange,提问作者Fravadona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 07:58:17