1

教科书 Intro to Algorithms (CLRS) 的问题 9-3描述了一种快速 O(n) 算法,用于查找长度为 n 的数组的第 k 阶统计量(排序时数组中的第 k 个元素),对于特定的k 远小于 n 的情况。当 n 为奇数时,我不确定该算法的正确性,并希望找到一种方法来证明它是正确的。

基本思想是我们首先将数组分成两半,第一部分包含 floor(n/2) 个元素,第二部分包含 ceil(n/2) 个元素。然后,我们将前半部分的每个元素与后半部分的相应元素“配对”。当 n 为奇数时,这会留下一个剩余的未配对元素。

对于每一对合作伙伴,我们确保左合作伙伴 >= 右合作伙伴,如果不是,则交换两者。然后,递归地找到下半场的 k 阶统计量,将下半场进行的任何交换与上半场的相应交换镜像。之后,整个数组的k阶统计量要么在前半部分的前k个元素中,要么在后半部分的前k个元素中。

我的困惑来自数组长度 n 为奇数的情况,并且后半部分有一个单独的元素没有伙伴。由于递归是在后半部分执行的,由数组的最后一个 ceil(n/2) 元素组成,包括唯一的无伙伴最后一个元素,我们应该将下半部分进行的所有交换与相应的交换中的交换进行镜像上半场的合作伙伴,当其中一个交换涉及到最后的元素时,不清楚该怎么做,因为它没有合作伙伴。

教科书似乎没有特别注意这个问题,所以我假设当交换涉及到最后一个元素时,那么上半场就不要做任何镜像动作。结果,最后一个元素只是简单地“窃取”了与之交换的任何人的伙伴。但是,在这种情况下,是否有一种简单的方法可以查看算法是否仍然正确?如果当最后一个元素窃取了别人的伙伴时,伙伴实际上是第 k 阶统计量,然后被交换到一个无法访问的位置怎么办?涉及顺序统计选择的递归和分区机制对我来说足够不透明,因此我不能自信地排除这种情况。

4

1 回答 1

2

我认为您对算法的描述并不完全准确(但是您链接到的解释远不清楚)。据我了解,该算法对于奇数长度数组正确的原因如下:

让我们先看几个偶数长度数组的例子,n=10 和 k=3(即我们正在寻找第三小的元素,即 2):

a.  5 2 7 6 1 9 3 8 4 0  
b.  5 1 7 6 2 9 3 8 4 0  
c.  5 0 7 6 2 9 3 8 4 1  
d.  5 0 7 6 2 9 3 8 1 4  

如果我们将数组分成两部分,我们会得到:

a.  5 2 7 6 1    9 3 8 4 0  
b.  5 1 7 6 2    9 3 8 4 0  
c.  5 0 7 6 2    9 3 8 4 1  
d.  5 0 7 6 2    9 3 8 1 4  

还有这些情侣:

a.  (5,9) (2,3) (7,8) (6,4) (1,0)  <- 0 coupled with 1
b.  (5,9) (1,3) (7,8) (6,4) (2,0)  <- 0 coupled with 2
c.  (5,9) (0,3) (7,8) (6,4) (2,1)  <- 1 coupled with 2
d.  (5,9) (0,3) (7,8) (6,1) (2,4)  <- 0, 1 and 2 not coupled with each other

在比较和交换这对夫妇以使他们的最小元素在第一组之后,我们得到:

a.  5 2 7 4 0    9 3 8 6 1  
b.  5 1 7 4 0    9 3 8 6 2  
c.  5 0 7 4 1    9 3 8 6 2  
d.  5 0 7 1 2    9 3 8 6 4  

你会看到最小的元素 0 总是在第一组。第二小的元素 1 要么在第一组,要么在第二组,如果它与最小的元素 0 耦合。第三小的元素 2 要么在第一组,要么在第二组,如果它与最小元素 0 或次小元素 1 耦合。

所以最小的元素在第一组中,第二和第三小的元素可以在任一组中。这意味着第三小的元素要么是第一组中的 3 个最小元素之一,要么是第二组中的 2 (!) 个最小元素之一。

a.  5 2 7 4 0    9 3 8 6 1  ->  0 2 4 + 1 3  
b.  5 1 7 4 0    9 3 8 6 2  ->  0 1 4 + 2 3  
c.  5 0 7 4 1    9 3 8 6 2  ->  0 1 4 + 2 3  
d.  5 0 7 1 2    9 3 8 6 4  ->  0 1 2 + 3 4  

因此,如果我们说整个数组的第 k 个最小元素现在是任一组中的第 k 个最小元素之一,那么第二组中就有一个可用的位置,这就是为什么,在一个奇数-长度数组,我们会将未耦合的元素添加到第二组。无论解耦元素是否是我们正在寻找的元素,它肯定是任一组中第 k 个最小的元素之一。

实际上更正确的说法是,第 k 个最小元素是第一组中的 k 个最小元素之一,或者是第二组中 k/2+1 个最小元素之一。我实际上不确定该算法是最优的,甚至是正确的。有很多重复的比较和交换正在进行,当交换另一组中的对应元素时跟踪一对夫妇并交换一组中的元素的想法似乎没有意义。

于 2017-12-15T06:34:57.443 回答