BFPRT算法的作者是5位真正的大牛(Blum 、 Floyd 、 Pratt 、 Rivest 、 Tarjan)。
BFPRT解決的問題十分經典,即從某n個元素的序列中選出第k大(第k小)的元素,通過巧妙的分析,BFPRT可以保證在最壞情況下仍為線性時間復雜度。
步驟
- 將n個元素每 5 個一組,分成n/5(上界)組。
- 取出每一組的中位數,任意排序方法,比如插入排序。
- 遞歸的調用 selection 算法查找上一步中所有中位數的中位數,設為x,偶數個中位數的情況下設定為選取中間小的一個。
- 用x來分割數組,設小於等於x的個數為k,大於x的個數即為n-k。
- 若i==k,返回x;若i<k,在小於x的元素中遞歸查找第i小的元素;若i>k,在大於x的元素中遞歸查找第i-k 小的元素。
終止條件:n=1 時,返回的即是i小元素。
================================ 待查找的數組 : 4 1 2 56 24 5 6 97 8 0 4 8 6 2 3 6 1 9 3 4 6 2 找出第 8 小的數 被分割的數組 : 4 1 2 56 24 該數組的中位數 : 4 被分割的數組 : 5 6 97 8 0 該數組的中位數 : 6 被分割的數組 : 4 8 6 2 3 該數組的中位數 : 4 被分割的數組 : 6 1 9 3 4 該數組的中位數 : 4 中位數的集合 : 4 6 4 4 經過選擇排序后的中位數數組 : 4 4 4 6 定義的 x 為 : 4 ================================ 待查找的數組 : 4 1 2 0 4 2 3 1 3 4 2 找出第 8 小的數 //數組長度比8大 被分割的數組 : 4 1 2 0 4 該數組的中位數 : 2 被分割的數組 : 2 3 1 3 4 該數組的中位數 : 3 中位數的集合 : 2 3 經過選擇排序后的中位數數組 : 2 3 定義的 x 為 : 2 //前6小的數據已得出(0 1 1 2 2 2) ================================ 待查找的數組 : 4 4 3 3 4 找出第 2 小的數 3 //(8-6=2 查出第二2小的數據) 第 8 小的數為 : 3
(0 1 1 2 2 2 3 3 4 4 4 5 6 6 6 6 8 8 9 24 56 97)
ps:
1.為何利用5作為元組大小,可能是與寄存器的數量和運算有關。
2.為何稱為線性的解答:
划分時以5個元素為一組求取中位數,共得到n/5個中位數,再遞歸求取中位數,復雜度為T(n/5)。
得到的中位數x作為主元進行划分,在n/5個中位數中,主元x大於其中1/2*n/5=n/10的中位數,而每個中位數在其本來的5個數的小組中又大於或等於其中的3個數,所以主元x至少大於所有數中的n/10*3=3/10*n個。同理,主元x至少小於所有數中的3/10*n個。即划分之后,任意一邊的長度至少為3/10,在最壞情況下,每次選擇都選到了7/10的那一部分,則遞歸的復雜度為T(7/10*n)。
在每5個數求中位數和划分的函數中,進行若干個次線性的掃描,其時間復雜度為c*n,其中c為常數。
其總的時間復雜度滿足: T(n)<=T(n/5)+T(7/10*n)+c*n
假設T(n)=x*n,其中x不一定是常數(比如x可以為n的倍數,則對應的T(n)=O(n^2))。則有 x*n <= x*n/5 + x*7/10*n + c*n。得到 x<=10*c
於是可以知道x與n無關,T(n)<=10*c*n,為線性時間復雜度算法。
而這又是最壞情況下的分析,故BFPRT可以在最壞情況下以線性時間求得n個數中的第k個數。