子集和枚举的时间复杂度

Time Complexity of Subset-Sum Enumeration

通常,在处理组合时,Big-O 复杂度似乎是 O(n choose k)。在此算法中,我生成数组中与目标总和相匹配的所有组合:

def combos(candidates,start, target):
    if target == 0:
        return [[]]
    res = []
    for i in range(start,len(candidates)):
        for c in combos(candidates, i+1, target-candidates[i]):
            res.append([candidates[i]]+ c)
    return res


print combos([2,1,10,5,6,4], 10)
# [[1, 5, 4], [10], [6, 4]]

我在这里很难确定 Big-O,这是 O(n choose t) 算法吗?如果不是,那是什么,为什么?

如果重点是根据集合大小给出worst-cast复杂度,n,那么就是Θ(2n)。给定任何集合,如果目标总和足够大,您将最终枚举该集合的所有可能子集。这就是Θ(2n),从两个方面可以看出:

  • 每一项可有可无

  • 就是你的Θ(n选k),只是总结了所有k.


更精确的边界将同时考虑 n 和目标总和 t。在这种情况下,按照上面第 2 点的推理,如果所有元素(和目标总和)都是正整数,那么复杂度将是 Θ(n choose k) 的总和对于 k 仅求和 t.

你的算法至少是 O(2^n),我相信是 O(n * 2^n)。这里有一个解释。

在您的算法中,您必须生成一个集合的所有可能组合(空集合除外)。所以这是:

O(2^n) 至少。现在对于每种组合,您都必须将它们相加。一些集合的长度为 1,长度为 n,但其中大多数的长度为 n/2。所以我相信你的复杂度接近 O(n * 2^n).