《算法導論》學習筆記-第九章 中位數和順序統計量


引入

本章主要講的是選擇問題,比如:求一組數列中的最大值和最小值,或者是求出第i大的元素。這個我們可能認爲很簡單,運用排序算法排序,再加上求出他們的索引。就可以很容易的得到。但是有沒有想過,如果是基於排序算法的話,排序算法的最低時間也是nlgn。所以本章主要討論是否存在比較小的代價來實現這個問題,探索出它的最優解。

在進入本章之間,需要說明幾個概念:

  • 順序統計量: 在一組由n個元素組成的集合中,第i個順序統計量就是該集合中第i大的元素
  • 中位數: 在這元素中的“中點元素”,當n爲奇數時,中位數是中位數在 i =(n + 1)/ 2 , 當n爲偶數時,則中位數出現在n/2(下中位數)和n/2+1(上中位數)處,本書中都取下中位數。

最小值和最大值

分別找出最小值和最大值

我們要在一組元素中,分別找出這組元素的最小值或者最大值,我們通常用到的是MINIMUN算法,這個算法的上下限都是n-1,就是說在n個數中相互比較n-1次,時間爲O(n),是求解這類問題的最優算法,該算法用C語言實現是:

void Minimun(int a[], int length)
{
	int min = a[0];
	for (int i = 1; i< n; i++){
		if (min > a[i])
			min = a[i]
	}
	return min   //返回最小值
}

同時求出最小值和最大值

如果說要同時求出一組數的最小值和最大值的時候,如果我們還用上面的算法來求得話,我們每個數就要比較兩次,總的比較次數就是2(n-1)次。但是下面介紹的一種只需要比較3n/2次的方法,思路就是兩數先進行比較,得到較大數和較小數,再將最大數和較大數比較,較小數和最小數比較。

期望爲線性時間的選擇算法

這裏就介紹一種用分治算法來解決選擇問題。該算法採用的是快速排序章節中的PARTITION過程來得到劃分的中點,如果該中點恰好等於選擇的點,我們要求的就是這個,否則再在左右兩個區間中用同樣的方法再次尋找。僞代碼是這樣的:

RANDOMIZED_SELECT(A,p,r,i)
       if p==r
          then return A[p]
       q = RANDOMIZED_PARTITION(A,p,r)
       k = q-p+1;
       if i==k
          then return A[q]
       else  if i<k
           then return RANDOMIZED_SELECT(A,p,q-1,i)
       else
           return RANDOMIZED_SELECT(A,p,q-1,i-k)

這裏A是數組A[p…r],選擇第i小的元素。
對於數組的劃分(PARTITION)僞代碼是:

PARTITION(A,p,r)
     x = A[r]
     i = p-1
     for j = p to r-1
         do if A[j] ≤ x
             then i ++
                   swap(A[i],A[j])
     swap(A[i+1],A[r])
     return i+1

大致過程如下:

在這裏插入圖片描述
這個算法的期望時間是O(n),但是最壞情況下是O(n2)。

最壞情況線性時間的選擇

執行下面的步驟可以得到,算法SELECT可以求出n>1的一組數中的第i小的元素:

  1. 將輸入數組的n個元素劃分爲n/5(向上取整)組,每組5個元素,且至多隻有一個組有剩下的n%5個元素組成。(爲何是5,而不是其他數,有點不明白。)

  2. 尋找每個組織中中位數。首先對每組中的元素(至多爲5個)進行插入排序,然後從排序後的序列中選擇出中位數。

  3. 對第2步中找出的n/5(向上取整)箇中位數,遞歸調用SELECT以找出其中位數x。(如果是偶數去下中位數)

  4. 調用PARTITION過程,按照中位數x對輸入數組進行劃分。確定中位數x的位置k。

  5. 如果i=k,則返回x。否則,如果i<k,則在地區間遞歸調用SELECT以找出第i小的元素,若干i>k,則在高區遞歸查找第(i-k)個最小元素

具體的實現步驟是(直觀的表達上面的意思):
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章