算法----中位數算法的妙用(更新中)


中位數算法O(N)有許多妙用,能夠在一些場合下替代 排序O(NlgN)

1. 中位數算法

求N個數組中的中位數即求第n/2大的數

算法導論中給出了兩種求第k大的數的算法

算法1: 隨機算法 平均復雜度O(n)

思路:利用quicksort的隨機版本的partition, 將數組分成2部分:

         if 左邊部分數目<k, 則在右邊遞歸搜索

         else if 左邊的數> k, 則在左邊遞歸搜索

          else  return a[partition];

算法2: 確定性算法 最壞復雜度O(n)


2. 三個例子

例題1:帶權中位數

n個數x[1], x[2],..., x[n], 各自帶有一個權重, w[1], w[2], ..., w[n], w的總和是1

求x[k]滿足 所有滿足x[i] < x[k]的元素的權重之和< 1/2, 所有滿足x[i] > x[k]的元素的權重之和 >=1/2;


算法1: 先排序O(NlgN), 從前往后遍歷數組,找到第一個x[k], 使得前k個元素的權重之和>=1/2, return x[k]

算法2: 分治: 用中位數算法,將問題的規模減半

思路: 其實這個題並不需要排序,我們僅僅需要找到 n個數中較小的K(未知)個數的集合,使得它的和<1/2, 其他元素的和>=1/2, 具體這兩個集合中的數並不需要排序。考慮用中位數算法來找這個集合。

偽代碼:   WeightedMid(a, i, j,  w)

                    mid = Select(a, i, j) //中位數算法

                    left_sum = w[i]+w[i+1]+...+w[mid-1]; //左半部分數組的權重和

                    right_sum = w[mid+1]+w[mid+1]+...w[j];

                    if left_sum >=w,  return WeightedMid(a, i, mid-1, w);

                    elseif right_sum >w, return WeightedMid(a, mid, j, w-left_sum);

                    else  return x[mid];

T(n) = T(n/2) + O(n)   


例題2: 部分背包問題:

一個竊賊去一家商店偷竊,有n件商品: 第i件物品值vi元,重wi榜(vi, wi都是整數),他的背包最多只能裝下W榜物品,

每件商品他可以選擇一部分帶走,而不像0-1背包問題。問他最多能帶走多貴的物品?


分析: 由於部分背包問題允許僅拿走物品的一部分,物件更像是金粉,可證明其具有貪心的性質。

算法1: 貪心

按照每榜的價值進行排序,然后由價值的大小依次往包里裝,直到重量為W。

算法復雜度是 O(nlgn).


能不能將其復雜度降低到線性呢?

注意到,無論是動態規划還是貪心,其實都具有問題可分(decomposed)的性質, 也就是可以考慮用分治(divide-and-conquer)。

要構造O(n)的算法,首先想到 T(n) = T(n/2) + O(n),

--------------- 在O(n)的時間內把問題的規模降為一半,那么就得到了一個O(N)的算法。

分析:

貪心算法時間復雜度主要是排序,可以不排序嗎?

  可以。排序只是為了找出那些單價高的物品集合,所以我們並不需要把所有的單價進行排序

我們只需要找到背包所能裝得下的那部分單價較高的物品即可。這類似於在數組中找前k大的k個數(復雜度是O(N)).

因此使用排序我們其實做了多余的比較。

目標:一分為二,而且要找的是前k大的k個數(k未知),

Bingo! 先找出中位數!


算法2:

n個物品的單價數組: A[1:n]

找出其中位數,將數組分成3個部分: A{單價高於中位數}   B{單價等於中位數}  C{單價小於中位數}

注意到 {A}, {A+B}, {C}的規模<=n/2

下面分三種情況:

1. 若集合A中的物品總質量 >= W, 遞歸在A中解部分背包問題

2. 若集合A中的物品總質量 < W, 且集合{A+B}中的物品總質量 >=W,  將A中物品全部裝入包中,剩余的從B中隨便取即可

3. 若集合{A+B}中的物品總質量 < W, 將A和B中的物品全部放入背包中,剩余的質量遞歸地在集合C中求解

復雜度分析:

求中位數復雜度是 O(N), 上述三種情況中除了子問題外,也頂多花O(N)時間,

T(n) <= T(n/2) + O(n)

所以 T(n) = O(n)


例3:

N個數中有一個數出現的次數大於1/2

算法1: 先排序,再掃描一次數組,記錄出現的次數 O(nlgn)

算法2: 這一問題其實也不需要排序。中位數即為所求。O(n)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM