以 awesomo 的答案为基础......如果我们可以假设数字是排序的,对于给定的 k,我们可以做得比 O(n^k) 更好;只需取所有大小为 (k-1) 的 O(n^(k-1)) 子集,然后在剩余的部分中进行二分搜索,找到一个数字,当添加到第一个 (k-1) 时,给出目标。这是 O(n^(k-1) log n)。这意味着复杂性肯定低于此。
事实上,如果我们知道 k=3 的复杂度为 O(n^2),我们可以在 k > 3 时做得更好:选择所有 (k-3)-子集,其中有 O(n^( k-3)),然后在剩余元素上解决 O(n^2) 中的问题。对于 k >= 3,这是 O(n^(k-1))。
但是,也许你可以做得更好?我会考虑这个的。
编辑:我最初打算添加很多建议对这个问题提出不同的看法,但我决定发布一个删节版。我鼓励其他发帖者看看他们是否认为这个想法有任何价值。分析很困难,但它可能已经足够疯狂了。
我们可以利用我们有一个固定的 k 以及奇数和偶数之和以某种方式表现这一事实来定义一个递归算法来解决这个问题。
首先,修改问题,以便在列表中同时包含偶数和奇数(如果全部为偶数,则可以通过除以 2 来完成,或者如果全部为奇数,则从数字中减去 1 并从目标总和中减去 k,然后重复有必要的)。
接下来,利用只有使用偶数个奇数才能达到偶数目标和的事实,并且仅使用奇数个奇数才能达到奇数目标和。生成适当的奇数子集,并使用偶数递归调用算法,总和减去被检查的奇数子集的总和,k 减去奇数子集的大小。当 k = 1 时,进行二分查找。如果曾经 k > n(不确定这是否会发生),则返回 false。
如果您的奇数很少,这可以让您非常快速地选择必须是获胜子集的一部分的术语,或者丢弃不能的术语。您可以使用减法技巧将具有大量偶数的问题转换为具有大量奇数的等效问题。因此,最坏的情况一定是偶数和奇数的数量非常相似......这就是我现在所处的位置。一个无用的宽松上限比蛮力差很多数量级,但我觉得这可能至少与蛮力一样好。欢迎提出想法!
EDIT2:上面的一个例子,用于说明。
{1, 2, 2, 6, 7, 7, 20}, k = 3, sum = 20.
Subset {}:
{2, 2, 6, 20}, k = 3, sum = 20
= {1, 1, 3, 10}, k = 3, sum = 10
Subset {}:
{10}, k = 3, sum = 10
Failure
Subset {1, 1}:
{10}, k = 1, sum = 8
Failure
Subset {1, 3}:
{10}, k = 1, sum = 6
Failure
Subset {1, 7}:
{2, 2, 6, 20}, k = 1, sum = 12
Failure
Subset {7, 7}:
{2, 2, 6, 20}, k = 1, sum = 6
Success