问题分析:在一个长为n的数组A[1..n]中,找到这样的i、j,使A[i...j]中元素的和最大,称A[i...j]为最大子数组。
算法一(分治思想):
数组A[low...high]的最大子数组必然满足三种情况:
1)子数组在A[low...mid]中;
2)子数组在A[mid+1,high]中;
3)子数组跨越中点mid。
因此可以使用递归分治方法计算find_max(A, low, high),其中满足:
find_max(A, low, high) = max(find_max(A, low, mid), find_max(A, mid+1, high), cross_max(A, low, high))
cross_max(A, low, high)函数的实现方法如下:
left-sum = A[mid] sum = 0 for i = mid downto low sum = sum + A[i] if sum > left-sum let-sum = sum max-left = i right-sum = A[mid+1] 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)
算法二(线性复杂度):
对于数组A[1...n],从左到右遍历数组,记录目前为止处理过的最大子数组,直到遍历完整个数组,具体思路如下:
对于1<=j<=n,记录A[1...j]的最大子数组和最大A[i...j]的值,那么A[1...j+1]的最大子数组为下面3种情况之一,取最优即可:
1)A[1...j]的最大子数组
2)A[i...j]+A[j+1]
3)A[j+1]
总结:分治方法可能会得到算法复杂度低于暴力求解的算法,对于某些问题,分治策略虽然能给出较优算法,但不使用该策略甚至可以能做得更好,该问题就是很好的例子。