问题在于:给定一系列数字,将这些数字拆分为2个序列,以便两个序列之间的差异最小。例如,给定序列:[5,4,3,3,3],解决方案是:
[5,4] - >总和是9
[3,3,3] - >总和是9
差异是0
换句话说,你能找到一个给定整数输入向量(可变大小)的算法(C语言首选),可以输出两个向量,其中两个和之间的差值最小吗?
应该避免残酷的算法。
为了确保获得正确的解决方案,最好在基准测试中比较算法和残酷力算法之间的结果。
答案 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的优化版本,这要困难得多。