最大子数组问题

最大子数组问题

一个数组如:

求解该数组内的一个子数组,该数组的元素属于A[ ],且元素是连续的,且子数组元素的和为A[]内所有子数组中最大的,则该数组为连续数组的最大子数组。

暴力求解方法

暴力求法,就是一个个的去遍历组合时间 为: T(n)=Θ(n2).

使用分治策略的求解方法

但是我们想要更短的时间求解最大子数组问题.那么它就是使用分治策略的求解方法。
使用分治策略的时候必然会遇到最大子数组位于哪里的问题,设数组A[ ] 的中央位置为mid,那么A[low..high]的连续的最大子数组A[i..j]位置必然是以下三种情况之一:

  • 完全位于子数组A[low..mid]中,因此有 lowijmid.
  • 完全位于数组A[mid+1..high]中, 因此 mid<ijhigh.
  • 跨越了中点,因此 lowimid<jhigh.
    如图:
    最大子数组问题_第1张图片

因为跨域中点的的最大子数组的情况并非原问题的规模更小的实例,所以我们先求出跨越中点mid的子数组.
任何跨越中点的子数组都由两个子数组A[i..mid]和A[mid+1..j]组成,其中 lowimid mid<jhigh. 因此我们只需要找出形如A[i..mid]和A[mid+1..j]的最大子数组,然后将其合并即可.

过程FIND-MAX-CORSSING-SUBARRAY接收,数组A和下标low、mid 和 high为输入,返回一个下标元组划定跨越中点的最大子数组的边界,并且返回最大子数组中值的和.
伪代码:

FIND-MAX-CORSSING-SUBARRAY

left_sum = -∞
sum = 0
for i = mid downto low
    sum = sum + A[i]
    if sum > left_sum
        left_sum = 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_summ)

如果子数组A[low..high]包含n个数组, 包含n个元素(即n=high - low + 1),则调用FIND-MAX-CORSSING-SUBARRAY(A, low, mid, high)花费 Θ(n) 时间。由于两个for循环的每次迭代花费 Θ(1) 时间,我们只需统计一共执行多少次迭代。第3~7行的for循环执行了 midlow+1 次迭代,第10~14行的for循环执行了 highmid 次迭代,因此总循环迭代次数为:
(midlow+1)+(high+mid)=highlow+1=n

有了FIND-MAX-CORSSING-SUBARRAY的线性时间那么我们,现在设计求解最大子数组问题的分治算法的伪代码:

FIND-MAXIMUM-SUBARRAY(A, low, high)

if high == low
    return (low, high, A[low])//base case:only one element
else mid = [(low + high)/2]
    (left_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-CORSSING-SUBARRAY(A, low, mid, high)
    if left_sum >= right_sum and left_sum >= cross_sum
        return (left_low, left_high, left_sum)
    else if right_sum >= left_sum and right_sum >= cross_sum
        return (right_low, right_high, right_sum)
    else return (cross_low, cross_high, cross_sum)

分治算法的分析

首先,第 1 行花费常量时间。对于 n = 1 基本情况,第2行花费时间常量时间,因此,

T(1)=Θ(1)

当n > 1时为递归情况, 第1和第3行花费常量时间。第4行和第5行求解的问题均为n/2个元素的子数组(假定原问题规模为2的幂,保证了n/2为整数),因此每个问题的求解时间为T(n/2)。因此第4行和第5行给总运行时间增加了2T(n/2)。而第6行调用FIND-MAX-CORSSING-SUBARRAY花费 Θ(n) 时间。第7~11行花费 Θ(1) 时间。因此对于递归情况,我们有
T(n)=Θ(1)+2T(n/2)+Θ(n)+Θ(1)=2T(n/2)+Θ(n)

综合以上有:
T(n)={Θ(1)n=12T(n/2)+Θ(n)n>1

其解为 T(n)=Θ(nlgn).

你可能感兴趣的:(算法,算法导论,分治策略,最大子数组问题)