求解最大子序列和的四种方法
1、三重循环暴力求解
例程:
int MaxSubsequenceSum(const int A[], int N)
{
int ThisSum, MaxSum, i, j, k;
MaxSum = 0;
for(int i = 0; i < N; i++)
for(int j = i; j < N; j++)
{
ThisSum = 0;
for(k = i; k <= j; k++)
ThisSum += A[k];
if(ThisSum > MaxSum)
MaxSum = ThisSum;
}
return MaxSum;
}
分析复杂度:
复杂度为
\[\sum^{n}_{i = 1}(\sum_{j = i}^n(j - i))
\]
而
\[\sum_{j = i}^n(j - i) = \frac{(n - i)(n - i + 1)}{2} = \frac{(n - i)^2}{2} + \frac{n- i}{2}
\]
\(\Rightarrow\)
\[\sum_{i = 1}^n(\frac{(n - i)^2}{2} + \frac{n - i}{2}) = O(n^3)
\]
2、两重循环
上面的三重循环可以撤除一个,以此来获取平方级别的复杂度
例程:
int MaxSubsequenceSum(const int A[], int N)
{
int ThisSum, MaxSum, i, j;
MaxSum = 0;
for(int i = 0; i < N; i++)
{
ThisSum = 0;
for(int j = i; j < N; j++)
{
ThisSum += A[j];
if(ThisSum > MaxSum)
MaxSum = ThisSum;
}
}
return MaxSum;
}
易知,复杂度为
\[\sum_{i = 1}^{n}(n - i) = O(n^2)
\]
3、分治
例程:
static int MaxSubSum(const int A[], int Left, int Right)
{
int MaxLeftSum, MaxRightSum; // 左右部分各自的最大子序列和
int MaxLeftBorderSum, MaxRightBorderSum; // 包括边界的左右最大子序列和的最大值(从中间开始往左右延伸),这两个数最后要相加到一起,然后和上面的两个数比较,它们的和的本质其实是跨越中间边界的最大子序列和
int LeftBorderSum, RightBorderSum; // 存储临时值
int center, i;
if(Left == Right)
if(A[Left] > 0)
return A[Left];
else
return 0;
Center = (Left + Right) / 2;
MaxLeftSum = MaxSubSum(A, Left, Center);
MaxRightSum = MaxSubSum(A, Center + 1, Right);
MaxLeftBorderSum = 0;
LeftBorderSum = 0;
for(i = Center; i >= Left; i—)
{
LeftBorderSum += A[i];
if(LeftBorderSum > MaxLeftBorderSum)
MaxLeftBorderSum = LeftBorderSum;
}
MaxRightBorderSum = 0;
RightBorderSum = 0;
for(i = Center + 1; i <= Right; i ++)
{
RightBorderSum += A[i];
if(RightBorderSum > MaxRightBorerSum)
MaxRightBorderSum = RightBorderSum;
}
return Max3(MaxLeftSum, MaxRightSum, MaxLeftBorderSum + MaxRightBorderSum);
}
int MaxSubSequenceSum(const int A[], int N)
{
return MaxSubSum(A, 0, N - 1);
}
\[T(n) = 2T(\frac{n}{2}) + O(n)
\]
\(\Rightarrow\)
\[T(n) = O(nlogn)
\]