假设我有n个元素,其值分别为x[i]
。让所有值的总和表示为X,并强制每个元素为x[i] <= X/2
。现在给定数组x[]
,如何将它分成两组(至少大小为1),使得每组的总和小于或等于2X / 3?
我已经为这个问题感到困惑了一段时间。我发现在某些情况下这实际上是不可能做到的,但否则我只会研究贪婪的方法:将元素x[i]
放入具有最小累积总和的分区中。关于如何解决此问题的任何想法?
答案 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的列表)以及总和(目前为止等于元素本身)。将这些插入到最小堆中,以总和为键。弹出最小的两个,合并它们(连接元素列表,添加总和),然后推回到最小堆中。漂洗并重复直到您的堆中有两个节点。现在,它们包含您的解决方案。