给定一个整数x和一个未排序的整数数组,描述一个算法 确定两个数字是否加起来为x。 (在这种情况下,不允许使用哈希表)。 解决方案是:
对数组进行排序。然后,跟踪数组中的两个指针,一个在 一开始,一开始。每当前两个整数的总和是 小于x,向前移动第一个指针,只要总和大于x, 向后移动第二个指针。如果找不到两个添加到x的数字 在其中一个指针遇到之前,则没有一对与x相加的整数。这个 解决方案需要O(n log n)时间,因为我们对数字进行排序。
我们可以为k
整数提供通用解决方案吗?上面说的问题适用于k=2
。我现在想要找3
整数target sum
,依此类推。
答案 0 :(得分:2)
只是为此设置一个上限...对于固定的k,问题总是在P(数字列表的大小的多项式,无论如何),并且可以通过简单的O求解( n ^ k)算法:生成k集(它们有C(n,k))并检查它们。对于k = 2的情况,这对应于生成所有n(n + 1)/ 2个两组并检查它们。
如果我们改为k <= n,则此问题等同于子集和问题,因此NP完全。
请注意,这些表示复杂性的严格上限...对于k = 2,您已经找到了O(n log n)算法,并且该方法可以推广到更高的k。
Edit2:删除了一些更严格的界限,因为看起来我的构造错了。抱歉搞砸了。支持spinning_plate的道具让我保持诚实。
答案 1 :(得分:0)
如果您可以使用任何数据结构,则只需将其视为knapsack problem,并跟踪除了总和之外您使用的数字。
numbers = [xxx]
buckets = [[0,0] for x in range(MAX_SUM)]
buckets[0][0] = 1;
for number in numbers:
for bucketi in range(MAX_SUM):
if buckets[bucketi][0] == 1 and buckets[bucketi][1] < k:
buckets[bucketi+number][0] = 1;
buckets[bucketi+number][1] = buckets[bucketi][1] + 1;
这也是对@Patrick所得到的尝试,我不确定这一点,但这是一个有趣的想法。
def go_(numbers, range_bottom,range_top,sum_target,k,min_v,max_v,nums):
min_v_,max_v_,res_ = go(numbers, range_bottom,range_top,sum_target-sum(nums),k)
min_v = min(min_v,min_v_)
max_v = max(max_v,max_v_)
if len(res_) > 0:
newres = [x for x in res_]
newres = newres+nums
return [0,0,newres]
return [min_v,max_v,res_]
def go(numbers, range_bottom,range_top,sum_target,k):
if sum_target==0 and k == 0:
return [0,0,['-']];
elif sum_target<0 or k==0 or range_bottom == range_top:
return [sum_target,sum_target,[]]
min_v = 666; max_v = -666;
if range_top-range_bottom>1:
min_v ,max_v, res_ = go_(numbers, range_bottom+1, range_top-1, sum_target,k-2,min_v,max_v,[numbers[range_bottom],numbers[range_top-1\
]])
if len(res_):
return [0,0,res_];
if not ( min_v<0 and max_v<0 ):
min_v ,max_v, res_ = go_(numbers, range_bottom+1, range_top, sum_target ,k,min_v,max_v ,[])
if len(res_):
return [0,0,res_];
if not ( min_v>0 and max_v>0 ):
min_v ,max_v, res_ = go_(numbers, range_bottom, range_top-1, sum_target,k,min_v,max_v,[])
if len(res_):
return [0,0,res_];
return [min_v,max_v,res_]
答案 2 :(得分:0)
我感觉这会有大量的挫折,因为我不会说数学(或CS语言),但我只是想出如何扩展你的方法
我假设
k = 3且x =总和
按升序对数组进行排序 将first_pointer放在第一个整数上,将second_pointer放在第二个整数上(即第一个指针旁边) 将third_pointer放在最后一个整数上。
<小时/>
表示k = 4且x =总和
按升序对数组进行排序 将前两个指针放在 A部分中 将第三个和第四个放在最后两个整数上,即第三个指针= second_last_integer和fourth_pointer = last_integer。
如果你到达这里没有任何sum = x,那么就没有解决方案//标准免责声明
<小时/>
(我的屏幕空间很小,因为我看不到我正在写的内容的预览。所以我会保持简短,让它保持你的想象力)
表示任何k和x =总和
按升序对数组进行排序 在开头放置第一个int(k / 2)指针 将其余的k-int(k / 2)指针放在末尾。
// p !!写了这么多!!