L 7 选择&对手论证
对手论证,一般用于给出问题的下界。若用P表示所讨论的问题,I表示问题的输入,A表示解决问题的基于比较运算的算法,T(A,I)表示对于输入I,算法A的计算时间复杂性,那么函数U(n)=min{max{T(A,I)}, for each I},for each A表示问题P在输入大小为n时在最坏情况下的最好时间下界,它是问题所固有的。
对手论证的基本思想是对每一个A构造一个输入特殊的输入I′,使T(A,I′)尽量地大,然后在所有A的集合上,求T(A,I′)的尽量小的下界作为f(n)。对手论证方法的关键在于有一套对于一切A的适用的构造符合要求的I′的策略,即对手策略,逐步第构造出一个输入I′,使算法A如果想达到预期的结果,要做尽量多次的比较和判断,从而使T(A,I′)尽量大。需要注意的是,一方面对手策略需具有一致性,即不能前后矛盾,以保证I′的存在性;另一方面对手策略还必须对一切A都适用,因为我们需要在一切A组成的集合上求T(A,I′)得下界。
1. Find 2nd Largest Number
我们知道,找到数组中元素的最大值,需要至少进行n−1次比较,那么找到第二大的呢?暴力算法就是在找一次最大呗,又是n−2次比较,总共是2n−3次比较。乍看起来也不错了,但是通过对手论证的分析,比较的总次数可以减少为n+⌈logn⌉−2次。How to?
其实,所谓的第二大的元素,应该是在比较中仅仅输给了最大元素,也就是说,只有跟最大的那个元素比过的败者才有可能是。我们下面要说明的是,我们要找的第二大的元素应该是在那些跟最大元素比过的⌈logn⌉个元素中。
在对手论证中,我们每次都是选择两两配对,然后进行比较,这样的话,每次配对完后的比较,数据规模都缩减一半,也就是说,总共经过⌈logn⌉轮的比较,把这些输给最大数的元素拿出来,进行一次find-Max,开销是O(⌈logn⌉)就可以找到第二大的啦!!
这里其实并不是严格的论证,只是证明了这个界是可以达到的,详细证明请参见这儿
2. Find Max and Min
这里也能够使用对手论证的方式得出其最少的比较次数为⌈23n⌉−2,具体的证明同样参见上述链接
下面,我们就来说说是怎么办到的吧,首先两两配对,共进行⌈21n⌉次比较,将这里面的胜者和败者分别分为两组,再在两组内分别挑选Max和Min,代价是2×(⌈21n⌉−1),这样就可以得到Max和Min,总共的比较次数就是⌈23n⌉−2啦。
每一行上,从快到慢排序,不失一般性,小组第一的就是X1, X=A,B,C,D,E,我们假设第六场比赛A1>B1>C1>D1>E1,>表示快的比较。那么A1一定是冠军!下面可能是第二、第三的只可能是A2,A3,B1,B2,C1这5个。为什么不可能是C2呢?因为C2至少输给了C1,而C1又至少输给了A1和B1,那么C2的最好成绩也不过是第四,其他的情况也是类似的分析。
所以在这第七场,遛一遛A2,A3,B1,B2,C1,就有第二、第三名产生了。