最大连续和
Posted 扶芥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最大连续和相关的知识,希望对你有一定的参考价值。
问题:给出一个长度为n的序列a1,a2,a3....an,求最大连续和,即找到1<=i<=j<=n,是的ai+...+aj最大
1.暴力枚举
int sum = 0;
int max = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
sum = 0;
for (int k = i; k <= j; k++)
sum += a[k];
if (max < sum)
max = sum;
}
}
T(n)=n(n+1)(n+2)/6=O(n3)
2.递推
利用前缀
int s[100];
int max = 0;
s[0] = a[0];
for (int i = 1; i < n; i++)
s[i] = s[i - 1] + a[i];
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int t = i == 0 ? s[j] : s[j] - s[i - 1];
max = Max(max, t);
}
}
T(n)=O(n2)
3.分治法
1)划分:把序列分成元素个数尽量相等的两半;
2) 递归求解:分别求出完全位于左半或者完全位于右半的最佳序列
3)合并:求出起点位于左半,终点位于右半的最大连续和序列,并和子问题的最优解比较
关键在于“合并”步骤,既然起点位于左半,终点位于右半,我们可以认为地把这样的序列分成两部分,
然后独立求解:先寻找最佳起点,然后再寻找最佳终点。
int maxsum3(int a[], int left, int right) { //左闭右开
int i, m, v, L, R, max;
if (right - left == 1) return a[left];
m = left + (right - left) / 2; //第一步,划分成[left,m),[m,right)
max = Max(maxsum3(a, left, m), maxsum3(a, m, right));
//第二步,递归求解
//第三步,合并
v = 0; L = a[m - 1];
for (i = m - 1; i >= left; i--)
L = Max(L, v += a[i]);
v = 0; R = a[m];
for (i = m; i < right; i++)
R = Max(R, v += a[i]);
return Max(max, L + R);
}
// 练习.cpp: 定义控制台应用程序的入口点。 // #include "stdafx.h" #include<iostream> #include<algorithm> #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include<time.h> #include<windows.h> using namespace std; int Max(int a, int b) { return a > b ? a : b; } //暴力枚举 int maxsum1(int a[], int n) { int sum = 0; int max = 0; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { sum = 0; for (int k = i; k <= j; k++) sum += a[k]; if (max < sum) max = sum; } } return max; } //递推前缀 int maxsum2(int a[], int n) { int s[100]; int max = 0; s[0] = a[0]; for (int i = 1; i < n; i++) s[i] = s[i - 1] + a[i]; for (int i = 0; i < n; i++) { for (int j = i; j < n; j++) { int t = i == 0 ? s[j] : s[j] - s[i - 1]; max = Max(max, t); } } return max; } //分治法 int maxsum3(int a[], int left, int right) { //左闭右开 int i, m, v, L, R, max; if (right - left == 1) return a[left]; m = left + (right - left) / 2; //第一步,划分成[left,m),[m,right) max = Max(maxsum3(a, left, m), maxsum3(a, m, right)); //第二步,递归求解 v = 0; L = a[m - 1]; //第三步,合并 for (i = m - 1; i >= left; i--) L = Max(L, v += a[i]); v = 0; R = a[m]; for (i = m; i < right; i++) R = Max(R, v += a[i]); return Max(max, L + R); } int main() { int n; int a[100]; cin >> n; for (int i = 0; i < n; i++) { cin >> a[i]; } int s1 = maxsum1(a, n); int s2 = maxsum2(a, n); int s3 = maxsum3(a, 0, n); cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; system("pause"); return 0; }
以上是关于最大连续和的主要内容,如果未能解决你的问题,请参考以下文章