分治策略——最大子数组问题

问题提出:如果知道股票的涨跌情况,如何选择在哪一天买进,哪一天卖出?

求解方法:

一、暴力求解

算出每两天的差值,这种差值一共存在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)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章