查找数组中的和等于零

时间:2011-01-31 08:52:32

标签: algorithm

给定一个整数数组,找到一组至少一个总和为0的整数。

例如,给定[-1, 8, 6, 7, 2, 1, -2, -5],算法可能会输出[-1, 6, 2, -2, -5],因为这是输入数组的一个子集,总和为0.

解决方案必须在多项式时间内运行。

3 个答案:

答案 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,否则不输出