分割2n个实数的序列,以便

时间:2009-11-30 00:22:12

标签: algorithm

我目前正在阅读The Algorithm Design Manual,我仍然坚持这项工作。


取一系列2n个实数作为输入。设计一个O(n log n)算法 将数字划分为n对,具有分区最小化的属性 一对的最大总和。例如,假设我们得到了数字(1,3,5,9)。 可能的分区是((1,3),(5,9)),((1,5),(3,9))和((1,9),(3,5))。这对 这些分区的总和是(4,14),(6,12)和(10,8)。因此第三个分区有 10作为其最大总和,这是三个分区的最小值。


我从一些例子中猜到,解决方案看起来像这样:

# in pseudo ruby code
a = [1,3,5,9]
pairs = []
while !a.empty?
    pairs << [a.shift, a.pop]  # [a.first, a.last]
end
pairs

但如何证明呢?

3 个答案:

答案 0 :(得分:9)

该算法有效,因为当x 0 ,x 1 ,... x 2n-1 是排序列表时,总会有包含(x 0 ,x 2n-1 )的最优解。

证明:

考虑包含的任何最优解(x 0 ,x 2n-1 )。它必须包含对(x 0 ,x a )和(x b ,x 2n-1 ) x 0 ≤x a ≤x 2n-1 和x 0 ≤x b ≤x 2n-1 。从解决方案中删除这些对,并放在它们的位置(x 0 ,x 2n-1 )和(x a ,x b'/子>)。两个新对的存在是否“破坏”了解决方案?该对(x 0 ,x 2n-1 )不能,因为它的和小于或等于(x b ,x 2n-1 ),它是原始最佳解决方案的成员。不能再次(x a ,x b )造成损害,因为其总和小于或等于(x b 的总和,x 2n-1 ),它是同一解决方案的成员。我们构建了一个 包含( 0 ,x 2n-1 )的最优解。

因此,您提供的算法绝不排除在任何步骤找到最佳解决方案的可能性,当只剩下两个值配对时,它们必须配对在一起。

答案 1 :(得分:3)

给定输入数组

x 0 x 1 x 2 ... x 2n

使用合并排序在O(n log n)时间内对其进行排序以生成排序列表

x a 0 x a 1 ... x a 2n < /子>

其中索引a i 表示您在初始列表上执行的排列以获得第二个列表。

我声称,所有配对产生最小最大总和的配对是以下配对:

(x a i ,x a 2n-i )i = 0,1,.... ..,n。也就是说,您将最高值的数字与可用的最低值数字组合在一起。

<强>证明

通过归纳进行,对于2n = 2的情况,这是显而易见的。

不失一般性,请考虑输入是已排序数字的列表(因为如果不是那么对它们进行排序)

x 0 x 1 x 2 ... x 2n

考虑x 2n 与任何数字的配对,然后很明显这个配对的最小总和是用(x 2n ,x 0 )。

现在考虑x 2n-1 的配对(x 2n ,x 0 ),(x 2n- 1 ,x 1 )是产生最小最大和的对,或(x 2n ,x 1 ),( x 2n-1 ,x 0 )是,或两者都是。在后一种情况下,我们的选择并不重要。在最后一秒的情况下,这是不可能的(考虑一下。)在一般情况下,如果我们通过这个过程归纳,当我们寻找x 2n-k 的对时,x < sub> k 是我们可以配对的最低未使用值,但是;相反,假设我们将x k 与其他x 2n-j 配对,j < k,试图获得更低的最低金额。这是不可能的,因为,x 2n-j + x k &gt; = x 2n-k + x k ,所以最多我们只能达到相同的最小金额。

这意味着选择(x 2n-k ,x k )给出了最小配对。

答案 2 :(得分:1)

我认为我可以证明这是一个没有重复数字的序列,对于读者来说,将证明扩展到非唯一序列应该是一个相当简单的练习。

将x 0 ,x 2n 组合在一起,然后根据最佳解决方案将所有其他数字配对。

现在考虑(x 0 ,x 2n )与任何其他对x y ,x z的配对来自最佳子集。 x 2n + x y 或x z 将大于x y + x z < / sub>以及x 2n + x 0 ,因此x 2n ,x 0 的配对是最优的

证据现在通过归纳扩展到X 1 ,X 2n-1 的配对,以及子集的其他分区,最终产生OP的配对。