1. 程式人生 > >中位數和順序統計量---演算法導論學習筆記

中位數和順序統計量---演算法導論學習筆記

演算法導論斷斷續續看了一小部分,但是還沒有寫過總結和筆記,很多思考和學習到的東西都隨著時間流失掉了(痛心)。
下面進入正題:
1.最大值和最小值問題
最簡單的確定一個有n個元素的集合中最小元素(最大元素)的方法就是所謂“打擂臺”的思路。遍歷集合,過程中將每個元素與現在所持有的最小元素進行比較,如果該元素小於現有最小元素則更新最小元素為該元素,否則繼續遍歷。可見至少要進行n-1次比較,從次數看來,這個演算法是最優的。
那麼,如果要同時找出最小元素和最大元素的話,該怎麼做?
(1).若n為奇數,則max=arr[0],min=arr[0];
若n為偶數,則max=arr[0],min=arr[1];
(2).集合中每兩個元素組成一對,分別求其大小關係。
(3).遍歷集合,將max和min與每對元素集中的最大元素與最小元素比較,進行更新
分奇數和偶數的情況是因為奇數個元素的集合不能被正好分成n/2個集合,所以乾脆將第一個元素孤立出來。
現在分析比較次數:
奇數:遍歷n/2個子集,max和min分別比較,加上每個子集內部比較,於是總共是3*floor(n/2)次.
偶數:第一次max和min子集的初始化比較,加上(n-2)/2個子集內部比較,加上遍歷的2*(n-2)/2次比較,所以總共是3n/2-2次比較。
2.選擇演算法(期望為線性時間)


這裡提供了一個分治演算法來確定集合中的第i個元素。

    (1).p為集合第一個元素,r為元素最後一個元素,q為分割槽關鍵字索引,i為所求元素在集合中的次序                    
    (2).對集合中的元素進行一次基於快速排序的隨機分割槽(randomized-patition),並得到分割槽關鍵元素的索引值q。
    (3).k=q-p+1,得到q之後的分割槽首元素,此時k代表q在該集合中的索引,而q得到的是整個集合中的索引值.
    (4).若k=i,則返回A「q」,
        若k>i,返回呼叫select(A,p,q-1,i)
        若k<i,返回呼叫select(A,q+1,r,i-k)

下面貼上java實現:

import java.util.Random;
public class RandomSelect {
    public static void exchange(int[] arr,int i,int j) {
        if(i<0||i>=arr.length||j<0||j>=arr.length||i==j)
            return;
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }

    public
static int patition(int[] arr,int p,int r) { Random random=new Random(); int index=Math.abs(random.nextInt(r)); while(index<p) index=Math.abs(random.nextInt(r)); exchange(arr,r,index); int x=arr[r]; int i=p-1; for(int j=p;j<r;j++) { if(arr[j]<x) { i++; exchange(arr,i,j); } } exchange(arr,i+1,r); return i+1; } public static int randomized_select(int[] arr,int p,int r,int i) { if(p==r) return arr[p]; int q=patition(arr,p,r); int k=q-p+1; if(k==i) return arr[q]; if(i<k) return randomized_select(arr,p,q-1,i); else return randomized_select(arr,q+1,r,i-k); } public static void main(String...args) { int[] arr={2,5,4,6,35,11,7,55,3,73,80}; System.out.println(randomized_select(arr,0,arr.length-1,arr.length)); } }

瞭解了基本的演算法,下面對時間期望進行分析:

k-1和n-k分割槽是隨機分區分出的兩個子集,對T(n)求期望值
E(T(n))<=E(nk=1·T(max(k1,nk)))+O(n)=1/n·E(T(max(k1,nk)))+O(n)
所以,E[T]<=2/n·k=n/2n1E[T(n)] 接下來將On(n)替換為an,並做一個假設:E[T(n)]<=cn
E[T]<=2/n·k=n/2n1ck+an=cn((cn/4)c/2an) (1) 具體的化簡請看《演算法導論》p122頁的演繹
最終,(cn/4)c/2an>=0 就可以證明(1)式至多為cn,得到結果n>=2c/(c4a)
如果假設對n<2c/(c4a),只要T(n)=O(1)那麼E(T(n))=O(n),期望為線性。因此,若集合元素互異,可以做到線上性時間內找到任一順序統計量