如何对列表进行分区

时间:2019-03-10 02:25:13

标签: algorithm greedy

假设我有n个元素,其值分别为x[i]。让所有值的总和表示为X,并强制每个元素为x[i] <= X/2。现在给定数组x[],如何将它分成两组(至少大小为1),使得每组的总和小于或等于2X / 3?

我已经为这个问题感到困惑了一段时间。我发现在某些情况下这实际上是不可能做到的,但否则我只会研究贪婪的方法:将元素x[i]放入具有最小累积总和的分区中。关于如何解决此问题的任何想法?

1 个答案:

答案 0 :(得分:0)

确定可以找到反例吗?我的数学可能是错误的,但是似乎不可能构造这样的列表。让我们注意,对于三个元素a <= b <= c的列表,我们可以将它们划分为[a, b], [c]。这是因为要使a + b大于总和的2/3,我们将有(a + b) * 3 > 2 * (a + b + c)a + b > 2 * c,这意味着a和/或{{1} }必须大于b

考虑到这一点,我们将数字分为三个箱,每个箱的总和小于c。请注意,如果我们有四个元素N/2,则可以将它们划分为a <= b <= c <= d。像以前一样重复逻辑,要使[a, b], [c], [d]大于a + b,我们需要N/2(a + b) * 2 > (a + b + c + d),这意味着a + b > c + d和/或{{ 1}}必须大于a

我们可以从这里无限期地重复此逻辑。以我们的列表为b,要使c大于x,我们需要a + b,而对于带有N/2或比(a + b) * 2 > sum(x)2都大的元素(所有长度为4或更大的列表都是这种情况)。

应用此递归逻辑,我们可以从a箱增加到三个箱,将它们视为第一段中的b数字,然后以此方式构造答案。

从算法上讲,创建一堆节点,其中包含数组中的每个元素(作为长度为1的列表)以及总和(目前为止等于元素本身)。将这些插入到最小堆中,以总和为键。弹出最小的两个,合并它们(连接元素列表,添加总和),然后推回到最小堆中。漂洗并重复直到您的堆中有两个节点。现在,它们包含您的解决方案。