最大子序列和问题也是基础算法,应用很广。
分而治之:
int maxSubsequenceSum(const int a[], int left, int right)
{
if (left == right)//base case
{
if (a[left] > 0)
return a[left];
else
return 0;
}
int maxLeftSum, maxRightSum;
int center;
center = (left + right) / 2;
maxLeftSum = maxSubsequenceSum(a, left, center);
maxRightSum = maxSubsequenceSum(a, center + 1, right);
int maxLeftBorderSum = 0, leftBorderSum = 0;
for (int i = center; i >= left; i--)
{
leftBorderSum += a[i];
if (leftBorderSum > maxLeftBorderSum)
maxLeftBorderSum = leftBorderSum;
}
int maxRightBorderSum = 0, rightBorderSum = 0;
for (int i = center + 1; i <= right; i++)
{
rightBorderSum += a[i];
if (rightBorderSum > maxRightBorderSum)
maxRightBorderSum = rightBorderSum;
}
return Max3(maxLeftSum, maxRightSum, maxLeftBorderSum + maxRightBorderSum);
}
复杂度:
每次递归规模减半,合并用时cN,所以T(N)=O(NlogN);
每次递归所需空间均为常数O(1),所以递归树中节点个数即为S(N),所以S(N)=O(N);
在线算法:
int maxSubsequenceSum(int a[], int left, int right)
{
int n = right - left + 1;
int thisSum = 0, maxSum = 0;
for (int i = 0; i < n; i++)
{
thisSum += a[i];
if (thisSum > maxSum)
maxSum = thisSum;
else
if (thisSum < 0)
thisSum = 0;
}
return maxSum;
}
复杂度:
在线算法,T(N)=O(N),S(N)=O(1);
最大子序列起始和结束位置的确定,代码:
int maxSubsequenceSum(const int a[], int left, int right,int *startIndex,int *endIndex)
{
int n = right - left + 1;
int thisSum = 0, maxSum = 0;
int tempStart=0;
*startIndex = *endIndex = 0;
for (int i = 0; i < n; i++)
{
thisSum += a[i];
if (thisSum > maxSum)
{
maxSum = thisSum;
*startIndex = tempStart;//ensure index of start and end
*endIndex = i;
}
else
{
if (thisSum <= 0)
{
thisSum = 0;
tempStart = i + 1;//maybe start
}
}
}
return maxSum;
}
大体思想如上,每次舍弃一段数据时,下一个位置都有可能是最大子序列的起始位置,每次更新maxSum时才能确定真正的开始和结束位置。