寻找第2小元素

分析: 看见题目中有lg(n) 项,首先应该想到的是分治法,算法的思路如下:(为简单起见,不考虑取整的问题)

将 n 个元素分成 n/2 对.每一对之间互相比较.这样一共比较了 n/2 次.然后将每一对的较小元素放在 S[1...n/2] 数组中,较大的元素对应的放在 B[1...n/2]中.显然最小的元素肯定在数组S中,那么第2小的元素(设代号为X)  是否也在 S 中呢?

首先,假设第2小元素X在数组S 中,因为最小的元素也在数组S中,所以X在S中同样也肯定是第2小元素.这样我们可以递归的在S中继续寻找第2小元素,并将搜索的范围缩小了一半.

如果第2小元素X不在数组S中,(即在数组B中),由上面的分区算法知,在B中的元素必然大于相应位置上S中的元素.在这里X是第2小元素,它仅大于最小元素.所以它在B中的位置与最小元素在S中的位置相同.

综上可知:第2小元素X要么是S中的第2小元素,要么是B中位置与最小元素在S中的位置相同的元素.

这样算法就很明了了: 将 n 个元素分成 n/2 对比较,较大者放入B,较小者放入S,若B和S的大小为1,则B[1]作为第2小元素返回,S[1]作为最小元素返回(主要是想得到最小元素在S中的位置),若B和S的大小大于1,则递归的在S中寻找最小元素和第2小元素,并将S中得到的第2小元素与B中位置与最小元素在S中的位置相同的元素相比较(有点拗口),其中较小者便是真正的第2小元素.

举个例子吧,如:   在序列 3,2,5,8,6,4,9,7 中寻找第2小元素.

过程:首先分在[3,2] [5,8] [6,4] [9,7] 四组,经比较后得到 S1=2,5,4,7    B1=3,8,9,7.

        再将 S1分区,得到  S2=2,4   B2=5,7 .

        S2中最小值是2,第2小元素是4. B2中与S2中最小值对应的是5,因4小于5.所以得到S1的最小值是2,第2小元素是4, 在B1中与S1中最小值2对应的是3,因4>3,所以得到 整个序列的第2小元素为 3.完成.

算法分析: T(n)=n/2+T(n/2)+1   //其中的n/2是分区时比较的次数,1 是递归时S中得到的第2小元素与B中位置与最小元素在S中的位置相同的元素相比较的消耗.

                  T(2)=1.

解递归式即可:T(n)=n+lg(n)-2 .

 

 

另解:

 

 

step1:对所有元素,两个一组比较大小,小的一个进入下一轮比较。一直到比较出最小的元素。此时所有比较结果构成一棵二叉树。比较次数为n-1。

step2:沿着树从树根向下到叶子,找出第二小的元素,比较次数是ceil[lgn]-1。令m2[p]表示以p为根的树中的第二小元素。对于当前处理结点为p,key[p] = min{key[left[p]], key[right[p]]}。假设key[p] =  key[left[p]],则m2[p] = min{m2[left[p]], key[right[p]]}