【问题标题】:Partitioning a list of integers to minimize difference of their sums对整数列表进行分区以最小化它们总和的差异
【发布时间】:2014-04-18 18:58:38
【问题描述】:

给定一个整数列表l,我如何将它分成两个列表ab,使得d(a,b) = abs(sum(a) - sum(b)) 最小。我知道问题是 NP 完全的,所以我正在寻找一个伪多项式时间算法,即O(c*n) 其中c = sum(l map abs)。我查看了Wikipedia,但是那里的算法将它分成精确的两半,这是我正在寻找的一个特例......

编辑: 为了澄清,我正在寻找确切的分区 ab 而不仅仅是由此产生的最小差异 d(a, b)

概括地说,什么是伪多项式时间算法,用于将n 数字列表划分为kg1, g2 ...gk 使得(max(S) - min(S)).absS = [sum(g1), sum(g2), ... sum(gk)] 处尽可能小

【问题讨论】:

  • 编辑过的问题(概括)完全改变了事情。 k-partitioning 是强 NP-Complete,没有已知的伪多项式解。

标签: algorithm big-o dynamic-programming partitioning np-complete


【解决方案1】:

一个天真的、平凡且仍然是伪多项式的解决方案是使用现有的解决方案进行子集求和,然后重复 sum(array)/2to 0(并返回找到的第一个)。

此解决方案的复杂度为O(W^2*n),其中W 是数组的总和。

伪代码:

for cand from sum(array)/2 to 0 descending:
   subset <- subsetSumSolver(array,cand)
   if subset != null:
        return subset

上面将返回小于/等于sum(array)/2的最大子集,另一部分是返回子集的补码。


不过,subset-sum的动态规划应该够用了。

回想一下公式是:

f(0,i) = true
f(x,0) = false | x != 0
f(x,i) = f(x-arr[i],i-1) OR f(x,i-1)

在构建矩阵时,如果您输入 sum(array)/2,上面实际上会为您创建每一行,其值低于初始 x - 它基本上是所有值。

生成DP矩阵后,只要找到x的最大值使得f(x,n)=true,这就是你能得到的最好的分区。

这种情况下的复杂度是O(Wn)

【讨论】:

  • 但这只是给了我 x,如果我真的想知道分区是什么??
  • @wrick 在此之后获取实际分区相当容易,只需按照给定x 的表格返回,并检查您在每个点做出的“决定”。我曾经在线程中解释过类似的背包算法:How to find which elements are in the bag, using Knapsack Algorithm (and not only the bag's value)?。如果您有任何困难,请尝试遵循并让我现在。
  • @wrick 对于表中的每个 1,请记住它是如何到达那里的。
【解决方案2】:

您可以将其表述为 0/1 整数线性规划优化问题。设 wi 为第 i 个数,设 xi 为 0/1 变量,指示 wi 是否在第一组中。然后你想最小化 sum(xi wi) - sum((1 - xi) wi) 受到

sum(xi wi) >= sum((1 - xi) wi)

并且还以所有 xi 为 0 或 1 为条件。已经有很多关于优化 0/1 线性规划求解器的研究。对于较大的总和 W,这可能是对 O(W n) 伪多项式时间算法的改进,因为 W 因子是可怕的。

【讨论】:

    【解决方案3】:

    我的第一个想法是:

    1. 整数列表排序
    2. 创建两个空列表 A 和 B
    3. 在从最大整数迭代到最小整数时...将下一个整数添加到当前总和最小的列表中。

    当然,这不能保证给你最好的结果,但你可以通过列表中最大整数的大小来限制它给你的结果

    【讨论】:

    • 这是子集和问题的非最优贪心解。 OP 澄清说他正在寻找优化的解决方案,并提供了了解最佳解决方案的链接。
    • Bleh -- 我看到了伪且虽然是伪最优(不是伪多项式)
    • 假设你有一个 n 个数字的序列,第一个 n-1 的值为 k,第 n 个值为 k(n-1)。那么你的解决方案就不是很理想了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-26
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多