算法与数据结构---4.2、最大子段和-枚举优化
一、总结
一句话总结:
对最大子段和的枚举优化,就是通过预处理来减少重复的计算
/* 枚举优化 可以把求和的那层循环去掉,我们可以对数据做预处理 用s[i]表示第一个数到第i个数这个序列的和 那么求s[i-j](第i个数到第j个数这个序列的和)的时候, 可以直接用s[j]-s[i]+a[i]即可 s[j]-s[i]表示的是i+1到j这个序列的和,所以需要加上a[i] 现在的时间复杂度: O(n)+O(n^2)=O(n^2) 优化方法: 减少重复计算 */ #include <iostream> using namespace std; int a[200005]; int s[200005]={0}; int main(){ int n; cin>>n; int maxx=-0x7fffffff; for(int i=1;i<=n;i++){ cin>>a[i]; s[i]=s[i-1]+a[i]; } //1、枚举每一段的起点和终点 for(int i=1;i<=n;i++){ for(int j=i;j<=n;j++){ //2、对每一段进行求和,在这些和里面选出最大的 int sum=s[j]-s[i]+a[i]; if(sum>maxx) maxx=sum; } } cout<<maxx<<endl; return 0; }
二、最大子段和-枚举优化
博客对应课程的视频位置:4.2、最大子段和-枚举优化
https://www.fanrenyi.com/video/27/264
1、题目描述
最大子段和(最大连续子序列的和)
题目描述
给出一个长度为 n 的序列 a,选出其中连续且非空的一段使得这段和最大。
输入格式
第一行是一个整数,表示序列的长度 n。
第二行有 n 个整数,第 i 个整数表示序列的第 i 个数字 ai
输出格式
输出一行一个整数表示答案。
输入输出样例
输入
7
2 -4 3 -1 2 -4 3
输出
4
说明/提示
样例解释
选取 [3,5] 子段{3,−1,2}最大,其和为 4。
数据规模与约定
对于40%的数据,保证n<=2×10^3
对于100%的数据,保证1<=n<=2×10^5, -10^4<=a[i]<=10^4
题目提交位置:
P1115 最大子段和 - 洛谷
https://www.luogu.com.cn/problem/P1115
2、枚举解法
1 /*
2 枚举法
3
4 分析:
5 我们可以直接按照题目的要求来枚举就好了
6
7 题目的要求是要 求a[1]-a[n]中连续非空的一段的和最大
8 那么我们把每个连续的一段都枚举出来,然后来算出里面的和,找出最大值即可
9
10 所以在这个需求下:
11 我们需要枚举每一段的起点、每一段的终点
12 然后对这一段进行求和
13
14 枚举变量:每一段的起点、终点
15 枚举范围:起点:1-n,终点:起点-n
16 枚举判断条件:
17 求和得到每一段的和,在这些和里面选出最大的
18
19 时间复杂度:
20 O(n^3)
21
22 算法思路:
23 1、枚举每一段的起点和终点
24 2、对每一段进行求和,在这些和里面选出最大的
25
26 */
27 #include <iostream>
28 using namespace std;
29 int a[200005];
30 int main(){
31 int n;
32 cin>>n;
33 int maxx=-0x7fffffff;
34 for(int i=1;i<=n;i++){
35 cin>>a[i];
36 }
37 //1、枚举每一段的起点和终点
38 for(int i=1;i<=n;i++){
39 for(int j=i;j<=n;j++){
40 //2、对每一段进行求和,在这些和里面选出最大的
41 int sum=0;
42 for(int k=i;k<=j;k++){
43 sum+=a[k];
44 }
45 if(sum>maxx) maxx=sum;
46 }
47 }
48 cout<<maxx<<endl;
49 return 0;
50 }
3、枚举优化
1 /* 2 枚举优化 3 4 可以把求和的那层循环去掉,我们可以对数据做预处理 5 用s[i]表示第一个数到第i个数这个序列的和 6 7 那么求s[i-j](第i个数到第j个数这个序列的和)的时候, 8 可以直接用s[j]-s[i]+a[i]即可 9 s[j]-s[i]表示的是i+1到j这个序列的和,所以需要加上a[i] 10 11 现在的时间复杂度: 12 O(n)+O(n^2)=O(n^2) 13 14 优化方法: 15 减少重复计算 16 17 18 */ 19 #include <iostream> 20 using namespace std; 21 int a[200005]; 22 int s[200005]={0}; 23 int main(){ 24 int n; 25 cin>>n; 26 int maxx=-0x7fffffff; 27 for(int i=1;i<=n;i++){ 28 cin>>a[i]; 29 s[i]=s[i-1]+a[i]; 30 } 31 //1、枚举每一段的起点和终点 32 for(int i=1;i<=n;i++){ 33 for(int j=i;j<=n;j++){ 34 //2、对每一段进行求和,在这些和里面选出最大的 35 int sum=s[j]-s[i]+a[i]; 36 if(sum>maxx) maxx=sum; 37 } 38 } 39 cout<<maxx<<endl; 40 return 0; 41 }