需要针对此问题的算法

时间:2010-06-01 18:09:09

标签: algorithm

有两个长度为N的整数序列A []和B [],都是未排序的。

要求:通过交换A []和B []之间的元素(可以随机交换,而不是使用相同的索引),区分{A []}中所有元素的总和与{所有元素的总和B []}中的元素最小。

PS:实际上,这是我遇到的面试问题。

非常感谢

6 个答案:

答案 0 :(得分:6)

这将是NP难!我相信你可以从Subset Sum减少到此。

根据BlueRaja / polygene的评论,我将尝试提供Subset Sum的完全减少。

这是一个减少:

子集和问题:给定整数x 1 ,x 2 ,...,x n ,是否有一些非空子集总和为零?

我们的问题:给定两个大小为k的整数数组,找到两个数组之和的最小可能差异,假设我们可以在数组中整数排列,将两个数组视为一个数组。

假设我们的问题有多项式时间算法。

现在说你得到整数T = {x 1 ,x 2 ,...,x n }(multiset)< / p>

设S i = x 1 + x 2 + ... + x n + x <子> I

设T i = {x 1 ,x 2 ,...,x i-1 ,x i + 1 ,...,x n }(= T - x i

定义

i =使用T i

形成的数组

B i = [S i ,0,...,0](即一个元素是S i ,其余为零)。

设m i =我们的问题找到的数组A i 和B i

的最小差异

(我们运行我们的问题n次)。

声明:当且仅当有一些i时,T的一些非空子集合为零,其中m i = 0。

证明:(wlog)说x 1 + x 2 + .. + x k = 0

然后

A = [x k + 1 ,...,x n ,0,... 0]

B = [x 2 ,x 3 ,...,x k ,S 1 , 0,.0]

给出最小差值m 1 为| x 2 + .. + x k +(x 1 + ... + x n )+ x 1 - (x k + 1 + .. + x n < /子>)| = | 2(x 1 + x 2 + .. x k )| = 0。

同样可以证明if部分。

实际上,这实际上也跟随(更容易)来自分区:只需创建全零的新数组。

我没有犯任何错误。

答案 1 :(得分:3)

采取NP-complete的任何实例partition problem

  

将一个正整数的多重A分成两个具有相同和的多重集B和C

喜欢{a 1 2 ,..., n }。添加n个零{0,0,0 ...,0,一个 1 ,...,一个 n }并询问该集合是否可以划分为两个多重集合A和B具有相同的总和和相同数量的元素。我声称这两个条件是等价的:

  • 如果A和B是问题的解决方案,那么你可以删除零并获得分区问题的解决方案。
  • 如果有分区问题的解决方案,例如 i1 + a i2 + ... a ik = a < sub> j1 + ... + a jl 其中{a i1 ,a i2 ,a ik j1 ,..., jl } = {a 1 ,...,a n }那么显然k + l = n。在左侧添加l个零,在右侧添加k,你将得到0 + ... + 0 + a i1 + a i2 + ... a ik = 0 + ... + 0 + a j1 + ... + a jl ,这是你的问题的解决方案。

所以,这是一个减少(所以问题是NP难),问题是NP,所以它是NP完全的。

答案 2 :(得分:2)

“长度为N”的序列A []和B [] - >这是否意味着A和B都每个长度为N?

(为了清楚起见,我在下面使用基于1的数组)。

如果是这样,那怎么样:

  1. 假设A [1..N]和B [1..N]
  2. 将A和B连接成长度为2N的新数组C:C [1..N]&lt; -A [1..N]; C [N + 1..2N]&lt; -B [1..N]
  3. 按升序排序C.
  4. 从C中取出第一个数字;将第一个元素(C [1])发送到A [1],将第二个元素(C [2])发送到B [1]
  5. 从C中取第二对数字;这次将第二个元素(C [4])发送到A [2],将第一个元素(C [3])发送到B [2](顺序为发送到A和B的对中的元素与3)
  6. 相反
  7. ...重复3和4直到C耗尽
  8. 这里的观察是,在排序的数组中,相邻的一对数字将具有最小的差异(与来自非相邻位置的一对数字相比)。步骤3确保A [1]和B [1]由一对具有最小可能差异的数字组成。步骤4确保(a)A [2]和B [2]由一对具有最小可能差异的数字(来自可用数字)组成,并且(b)差异与步骤3中的符号相反。像这样继续,我们确保A [i]和B [i]包含差异最小的数字。此外,通过翻转我们将元素发送到A和B的顺序,我们确保每个连续的i的差异发生变化。

答案 3 :(得分:1)

试着对它贪婪。鉴于这些有限的信息,我不确定那里还有什么可以推出。

答案 4 :(得分:0)

我不确定这是否会确保最小可能距离,但首先要考虑的是这样的事情:

int diff=0;
    for (int i = 0; i<len; i++){
        int x = a[i] - b[i];
        if (abs(diff - x) > abs(diff + x)){
             swap(a,b,i);
             diff-=x;
        }else{
             diff+=x;
        }

    }

假设您有一个交换函数,它接受两个数组并交换位置i处的项目:)

计算并添加位置i处两个值之间的差值,可以得到两个数组之和的增量差值。
在每一步,你检查是否更好地添加(a [i] -b [i])或(b [i] -a [i])。如果b [i] -a [i]就是这种情况,你可以交换数组中位置i的元素
也许这不是最好的方式,但它应该是一个开始:)

答案 5 :(得分:0)

问题是NP-Complete。

我们可以将此问题的partition problem减少到决策版,即给定两个相同大小的整数数组,确定是否可以交换项目以使总和相等

分区问题的输入:整数S,大小为N

为了将此输入转换为我们问题的输入,我们将A定义为S中所有项的数组,B定义相同大小的数组,对于所有i,B [i] = 0。此转换在输入大小上是线性的。

很明显,当且仅当S分区为2个子集以使得总和相等时,我们在A和B上应用的算法才返回true。