将数组分成n个部分的算法

时间:2014-11-21 16:06:15

标签: algorithm

在最近的一次Facebook采访中,我要求将一个数组分成3个相等的部分,使得每个数组中的总和大致等于sum / 3.(
我的方法
1 。排序阵列
2。填充数组[k](k = 0)uptil(array [k]< = sum / 3)
3。在该增量k之后,对数组[k]重复上述步骤。是否有更好的算法,或者是NP难问题

2 个答案:

答案 0 :(得分:1)

这是分区问题的变体(有关详细信息,请参阅http://en.wikipedia.org/wiki/Partition_problem)。事实上,解决这个问题可以解决这个问题(拿一个数组,填充0,然后解决这个问题)所以这个问题很难解决。

有一种伪多项式的动态编程方法。对于从i到数组大小的每个0,您可以跟踪子阵列当前大小的所有可能组合及其当前总和。只要数组中可能的子集数量有限,就可以快速运行。

我建议的解决方案就是去追求“足够好”。首先让我们考虑所有值为正的更简单的问题。然后按值降序排序。把阵列拿到三分。通过始终将最大的三元组添加到具有最小总和的三元组中来构建三个子集,最小的三元组与最大的三元组和中间到中间的三元组。您将最终均匀地划分数组,差异将不会超过第三个最小元素的值。

对于一般情况,你可以分为正面和负面,在每一个上使用上面的方法,然后暴力强制一组正面,一组负面和中间没有的少数剩余值的所有组合均匀分配。

答案 1 :(得分:0)

如果您有兴趣,请参阅动态编程解决方案的详细信息。运行时间和内存使用量为O(n *(sum)^ 2)其中n是数组的大小,sum是数组值绝对值的总和。对于从1到n的每个数组索引j,当​​您将数组从索引1分割为j到3个子集时,存储3个子集和可以获得的所有可能值。此外,对于每种可能性,存储一种可能的方式来分割数组以获得3个总和。然后在给定1到j的信息的情况下将此信息扩展为1到(j + 1),只需将3个和的每个可能组合分成1到j,并形成当您选择添加时得到的3个和的3个组合。 (j + 1)个数组元素到3个子集中的任何一个。最后,当你完成并达到j = n时,通过你将数组位置1到n分成3组时可以获得的3个子集和的所有组合的集合,并选择与sum / 3的最大偏差是最小化。首先,这可能看起来像是O(n *(sum)^ 3)复杂度,但是对于每个j和前2个子集和的每个组合,第3子集和是唯一确定的。 (因为不允许省略数组的任何元素)。因此,复杂性实际上是O(n *(sum)^ 2)。