给定一个整数数组,找到一组至少一个总和为0的整数。
例如,给定[-1, 8, 6, 7, 2, 1, -2, -5]
,算法可能会输出[-1, 6, 2, -2, -5]
,因为这是输入数组的一个子集,总和为0.
解决方案必须在多项式时间内运行。
答案 0 :(得分:8)
您将很难在多项式时间内执行此操作,因为此问题称为Subset sum problem,并且已知为NP-complete。
如果你确实找到了一个多项式解决方案,你就可以解决“P = NP?”问题,这会让你变得非常富有。
与已知多项式解最接近的是近似值,例如the one listed on Wikipedia,它将尝试以接近但不一定等于0的总和得到答案。
答案 1 :(得分:4)
这是一个Subset sum问题,它是NP-Compelete,但它有伪多项式时间算法。见维基。
如果集合中的项目总和与项目数量多项式相关,则可以在多项式中解决问题,来自wiki:
问题可以解决如下 使用动态编程。假设 序列是
x1, ..., xn
我们希望确定是否有 非空子集,总和为0.设N 是负值和的总和 P是正值的总和。 定义布尔值函数 Q(i,s)是值(真或假) 的
"there is a nonempty subset of x1, ..., xi which sums to s".
因此,问题的解决方案是 Q(n,0)的值。
显然,如果s <,则Q(i,s)=假。 N或s
因此不需要存储或计算这些值。创建一个数组 保持值Q(i,s)为1≤i≤n 和N≤s≤P。
现在可以使用a填充数组 简单的递归。最初,对于N≤s ≤P,设定
Q(1,s) := (x1 = s).
然后,对于i = 2,...,n,设置
Q(i,s) := Q(i − 1,s) or (xi = s) or Q(i − 1,s − xi) for N ≤ s ≤ P.
对于每个作业,Q的值 在右边已经知道, 或者是因为它们存储在 表的前一个值为i或 因为Q(i - 1,s - xi)=假,如果s - xi&lt; N或s-xi> P.因此, 算术运算总数 是O(n(P - N))。例如,如果全部 对于某些k,值为O(nk),然后 所需时间为O(nk + 2)。
该算法很容易修改为 如果存在,则返回带有和0的子集 是一个。
此解决方案不算作 复杂性理论中的多项式时间 因为P - N不是多项式的 问题的大小,这是 用于表示它的位数。 该算法是多项式的 N和P的值,它们是 它们的位数指数。
更普遍的问题是要求a 子集求和到指定值 (不一定是0)。它可以解决 通过简单的修改 上面的算法。对于这种情况 每个xi都是正的并且受到限制 同样不变,皮辛格发现了一个线性的 时间算法。[2]
答案 2 :(得分:1)
众所周知Subset sum problem NP完全问题。
如果你对算法很感兴趣,那么很可能你是数学爱好者,我建议你看看
在这里你可以找到它的算法
初始化列表S以包含一个元素0。
对于从1到N的每个i
让T为由xi + y组成的列表, 对于所有人在S
让你成为T和S的联盟 排序U使S为空
让y成为U
的最小元素将y添加到S
表示U in的每个元素z 增加订单//修剪列表 消除数字 彼此靠近 如果y <(1-c / N)z,则设置y = z并将z加到S
如果S包含(1-c)s和s之间的数字,则输出yes,否则不输出