algorithm - 将一组值分成两组具有相似值和的相同或相似大小

标签 algorithm partition-problem

我有一组浮点值,我想将它们分成两个大小最多相差一个元素的集合。此外,两组值之和的差异应该是最小的。可选地,如果元素的数量是奇数且总和不能相等,则较小的集合应该具有较大的总和。

那将是最佳解决方案,但我真的只需要一个关于子集大小约束的精确解决方案。总和的差异并不严格需要最小,但应该接近。另外,我希望较小的集合(如果有的话)具有较大的总和。

我意识到这可能与 partition problem 有关,但并不完全相同,也不严格。

我目前的算法如下,不过我想知道是否有办法改进它:

arbitrarily divide the set into two sets of the same size (or 1 element size difference)
do
  diffOfSums := sum1 - sum2
  foundBetter := false
  betterDiff := 0.0

  foreach pair of elements from set1 and set2 do
    if |diffOfSums - 2 * betterDiff| > |diffOfSums - 2 * (value1 - value2)| then
      foundBetter := true
      betterDiff := value1 - value2
    endif
  done

  if foundBetter then swap the found elements
while foundBetter

我对这种方法的问题是我不确定实际的复杂性以及是否可以对其进行改进。它当然不满足留下较小子集与较大总和的要求。

是否有任何现有算法恰好可以实现我想要实现的目标?如果没有,您能否建议我改进算法或找出它可能已经相当适合解决问题的方法?

最佳答案

很容易证明划分问题在多项式时间内可以简化为这个问题。

假设你想解决某个数组 A 的分区问题,但你只知道如何解决你的问题。您只需要将数组长度加倍,并用零填充即可。如果你能用你的算法解决它,那么你就解决了分区问题。这证明您的问题是 NP 难的。

但是您会发现您无法将此问题简化为分区(即它不是 NP 完全问题),除非您限制 float 的精度。在那种情况下,相同的算法将同时解决这两个问题。

在一般情况下,您能做的最好的事情就是回溯。

关于algorithm - 将一组值分成两组具有相似值和的相同或相似大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51220863/

相关文章:

algorithm - 关于来自 wiki 的加泰罗尼亚数字的表达

algorithm - 寻找分区问题算法返回 true 的最大值子集

algorithm - 寻找一种干净高效的算法来检查 "tree"(实际上是 DAG)的元素

algorithm - 你如何找到一个数字属于弗洛伊德三角中的哪一行和哪一列

Athena 中按日期列分区

algorithm - 在matlab中调用一个函数

algorithm - 将列表分成两等份算法

java - B+树先插入

java - Apriori 算法给出内存位置