1. 程式人生 > >分治策略——最大子陣列問題

分治策略——最大子陣列問題

問題提出:如果知道股票的漲跌情況,如何選擇在哪一天買進,哪一天賣出?

求解方法:

一、暴力求解

算出每兩天的差值,這種差值一共存在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)