最大连续和 C++实现 多种方法
方法一:暴力法,通过循环实现。通过对tot数值的观察可以发现,随着问题规模的变大,操作次数极度扩张。时间复杂度T(n)=O(n3)。
#include<cstdio>
#include<iostream>
#include<cstring>
int A[] = { 1,-2,3,4,5,6,-7,1,3,-5,-10,1 };
int main() {
int tot = 0;
int best = A[1];
int n = 11;
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
{
int sum = 0;
for (int k = i; k <= j; k++)
{
sum += A[k];
tot++;
}
if (sum > best) best = sum;
}
printf("%d\n", best);
printf("%d", tot);
}
方法二:利用数列前n项和S的启发,代码进行优化。此时时间复杂度T(n)=O(n2),基本操作次数明显减少。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100;
int A[] = { 1,-2,3,4,5,6,-7,1,3,-5,-10,1 };
int S[maxn];
int main() {
int tot = 0;
int best = A[1];
int n = 11;
/*for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
{
int sum = 0;
for (int k = i; k <= j; k++)
{
sum += A[k];
tot++;
}
if (sum > best) best = sum;
}*/
S[0] = A[0];
for (int i = 1; i <= n; i++)
{
S[i] = S[i - 1] + A[i];
}
for (int i = 1; i <= n; i++)
{
for (int j = i; j <= n; j++){
best = max(best, S[j] - S[i - 1]);
tot++;
}
}
printf("%d\n", best);
printf("%d", tot);
}
方法三:分治法。
分治算法的一般过程为。
划分问题:把问题的实例划分成子问题。
递归求解:递归解决子问题。
合并问题:合并子问题的解得到原问题的解。
本例中,划分就是把序列分成元素个数尽量相等的两半;递归求解就是分别求出左半和右半的最佳序列;合并就是求出起点位于左半、终点位于右半的最大连续和序列,并和子问题的最优解比较。
T(n)=O(nlogn)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int maxsum(int* A, int x, int y) {
int v, L, R, maxs;
if (y - x == 1) return A[x];
int m = x + (y - x) / 2;
maxs = max(maxsum(A, x, m), maxsum(A, m, y));
//int v, L, R;
v = 0;
L = A[m - 1];
for (int i = m-1; i >= x; i--)
L = max(L, v += A[i]);
v = 0;
R = A[m];
for (int i = 0; i < y; i++)
{
R = max(R, v += A[i]);
return max(maxs, L + R);
}
}
const int maxn = 100;
int A[] = { 1,-2,3,4,5,6,-7,1,3,-5,-10,1 };
int S[maxn];
int main() {
int tot = 0;
int best = A[1];
int n = 11;
printf("%d", maxsum(A,0,11));
}