一个数组如:
求解该数组内的一个子数组,该数组的元素属于A[ ],且元素是连续的,且子数组元素的和为A[]内所有子数组中最大的,则该数组为连续数组的最大子数组。
暴力求法,就是一个个的去遍历组合时间 为: T(n)=Θ(n2).
但是我们想要更短的时间求解最大子数组问题.那么它就是使用分治策略的求解方法。
使用分治策略的时候必然会遇到最大子数组位于哪里的问题,设数组A[ ] 的中央位置为mid,那么A[low..high]的连续的最大子数组A[i..j]位置必然是以下三种情况之一:
因为跨域中点的的最大子数组的情况并非原问题的规模更小的实例,所以我们先求出跨越中点mid的子数组.
任何跨越中点的子数组都由两个子数组A[i..mid]和A[mid+1..j]组成,其中 low≤i≤mid 且 mid<j≤high. 因此我们只需要找出形如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循环执行了 mid−low+1 次迭代,第10~14行的for循环执行了 high−mid 次迭代,因此总循环迭代次数为:
(mid−low+1)+(high+mid)=high−low+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行花费时间常量时间,因此,