分治策略——最大子陣列問題
阿新 • • 發佈:2019-02-17
問題提出:如果知道股票的漲跌情況,如何選擇在哪一天買進,哪一天賣出?
求解方法:
一、暴力求解
算出每兩天的差值,這種差值一共存在n(n-1)/2個。而處理每對日期所花費的時間至少也是常量。所以這種方法的時間複雜度為Ω(n^2)。
二、問題變化——分治策略
把後一天相對前一天的漲跌情況列為陣列,尋找和最大的非空連續子陣列,即最大子陣列。雖然看上去需要(n-1)(n-2)/2種情況,但終歸是有了約束,可以利用約束來做一些事情。
考慮分治策略,把陣列從中間分開,分為兩個子陣列,那麼最大子陣列出現的情況,只有三種:
1.完全包含在左邊的陣列中
2.完全包含在右邊的陣列中
3.跨越了中間值
對於1,2兩種情況,就是利用分治策略的時機了。至於第三種情況,因為包含了中間值,所以只需要線性時間就可以找到。
Find-MAX-CROSSING-SUBARRAY(A,low,mid,high) left-sum = 無窮小 sum = 0 for i = mid downto low sum = sum+A[i] if sum > lef-sum max-left = i right-sum = 無窮小 sum = 0 for j = mid + 1 to high sum = sum + A[j] if sum > right-sum right-sum = sum max-right = j return (max-left,max-right,left-sum + right-sum)
上述程式碼解決了跨越中間值的最大子陣列的問題。有了上述解決方法,那麼分治策略就很好進行了
FIND-MAXIMUM-SUBARRAY(A,low,high) if high =low return (low,high,A[low]) else mid = (low+high)/2 (lef-low,left-high,left-sum) = FIND-MAXIMUM-SUBARRAY(A,low,mid) (right-low,right-high,right-sum) = FIND-MAXIMUM-SUBARRAY(A,mid+1,high) (cross-low,cross-high,cross-sum) = FIND-MAX-CROSSING_SUBARRAY(A,low,mid,high) if left-sum>=right-sum AND left-sum>= cross-sum return (left-low,left-high,left-sum) elseif right-sum>=left-sum AND right-sum >= cross-sum return (right-low,right-high,right-sum) else return (cross-low,cross-high,cross-sum)
T(n) = 2T(n/2)+Θ(n)
所以T(n) = Θ(nlgn)