算法比较
最大连续子段和:求\(\max\sum\limits_{k=i}^jA_k\).
算法1:暴力枚举端点 \(T(N)=O(N^3)\)
int MaxSubsequenceSum(const int A[], int N) {
int ThisSum, MaxSum, i, j, k;
MaxSum = 0;
for (i = 0; i < N; i++)
for (j = i; j < N; j++) {
ThisSum = 0;
for (k = i; k <= j; k++)
ThisSum += A[k];
if (ThisSum > MaxSum)
MaxSum = ThisSum;
}
return MaxSum;
}
算法2:暴力枚举端点 \(T(N)=O(N^2)\)
int MaxSubsequenceSum(const int A[], int N) {
int ThisSum, MaxSum, i, j, k;
MaxSum = 0;
for (i = 0; i < N; i++) {
ThisSum = 0;
for (j = i; j < N; j++) {
ThisSum += A[j];
if (ThisSum > MaxSum)
MaxSum = ThisSum;
}
}
return MaxSum;
}
算法3:分治
- 递:分别求解左右区间的最大子段和
- 归:求解跨越中点的最大子段和:从中间向两端扫描
复杂度:\(T(N)=2T(N/2)+cN,\quad T(1)=O(1)\)
\(T(N)=2^kO(1)+cKN\quad \therefore T(N)=O(N\log N)\)
int MaxSubsequenceSum(const int A[], int l, int r) {
if (l == r) return max(A[l], 0);
int LeftSum, RightSum, MidSum, mid;
mid = (l + r) << 1;
LeftSum = MaxSubsequence(A, l, mid);
RightSum = MaxSubsequence(A, mid + 1, r);
int LeftMax = 0, RightMax = 0, ThisSum = 0;
for (int i = mid; i >= l; i--) {
ThisSum += A[i];
LeftMax = max(LeftMax, ThisSum);
}
ThisSum = 0;
for (int i = mid + 1, i <= r; i++) {
ThisSum += A[i];
RightSum = max(RightSum, ThisSum);
}
MidSum = LeftSum + RightSum;
return max(max(LeftSum, RightSum), MidSum);
}
算法4:贪心(在线算法) \(T(N)=O(N)\)
原理:\(f(n)=\max\set{0,f(n-1)+A_n}\)
int MaxSubsequenceSum(const int A[], int N) {
int ThisSum, MaxSum, j;
ThisSum = MaxSum = 0;
for (j = 0; j < N; j++) {
ThisSum += A[j];
if (ThisSum > MaxSum) MaxSum = ThisSum;
else if (ThisSum < 0) ThisSum = 0;
}
return MaxSum;
}
对数时间复杂度:
- 二分查找 \(T(N)=O(\log N)\)
算法分析检查:\(T(N)=O(f(N))\Leftrightarrow\lim\limits_{N\to\infty}\dfrac{T(N)}{f(N)}\approx Constant\)