查找算法以将序列拆分为2以最小化总和的差异

时间:2013-03-18 09:02:17

标签: algorithm

问题在于:给定一系列数字,将这些数字拆分为2个序列,以便两个序列之间的差异最小。例如,给定序列:[5,4,3,3,3],解决方案是:
[5,4] - >总和是9
[3,3,3] - >总和是9
差异是0

换句话说,你能找到一个给定整数输入向量(可变大小)的算法(C语言首选),可以输出两个向量,其中两个和之间的差值最小吗?
应该避免残酷的算法。

为了确保获得正确的解决方案,最好在基准测试中比较算法和残酷力算法之间的结果。

1 个答案:

答案 0 :(得分:2)

这听起来像是一个子阵列问题(这是我对"序列"的解释)。

意味着5, 4, 3, 3, 3的唯一可能性是:

| 5, 4, 3, 3, 3  =>  0 - 18 => 18
 5 | 4, 3, 3, 3  =>  5 - 13 => 8
 5, 4 | 3, 3, 3  =>  9 -  9 => 0
 5, 4, 3 | 3, 3  => 12 -  6 => 6
 5, 4, 3, 3 | 3  => 15 -  3 => 12
 5, 4, 3, 3, 3 | => 18 -  0 => 18 (same as first)

只需比较每个指数两边的总和即可。

代码:(未经测试)

int total = 0;
for (int i = 0; i < n; i++)
  total += arr[i];
int best = INT_MAX, bestPos = -1, current = 0;
for (int i = 0; i < n; i++)
{
  current += arr[i];
  int diff = abs(current - total);
  if (diff < best)
  {
    best = diff;
    bestPos = i;
  }
  // else break; - optimisation, may not work
}

printf("The best position is at %d\n", bestPos);

以上是O(n),从逻辑上讲,你做得不够好。

您可以通过对序列执行二进制搜索过程来略微优化上述内容,以降低n + log n而不是2n,但两者都是{{ 1}}。基本伪代码:

O(n)

如果它实际上是子集,那么,如前所述,它似乎是the Partition problem的优化版本,这要困难得多。