标签:nbsp 问题 col 小数 main 时间复杂度 开始 最小 cst
想法:从前往后遍历的时候记录最大值和最小值,如果当前最大值在最小值的后面,更新差值的最大值
1 #include <algorithm> 2 #include <iostream> 3 #include <vector> 4 #include <cstdio> 5 6 using namespace std; 7 8 int readint(){ 9 int x;scanf("%d",&x);return x; 10 } 11 12 int main() 13 { 14 vector<int>a; 15 int n,maxn,minn,value_maxn; 16 scanf("%d",&n); 17 for(int i=0;i<n;i++){ 18 a.push_back(readint()); 19 } 20 for(int i=0;i<n;i++){ 21 if(i==0){ 22 maxn=minn=a[i]; 23 value_maxn=0; 24 } 25 26 if(a[i]<minn){ 27 maxn=minn=a[i]; 28 } 29 if(a[i]>maxn){ 30 maxn=a[i]; 31 if(maxn-minn>value_maxn) 32 value_maxn=maxn-minn; 33 } 34 } 35 printf("%d\n",value_maxn); 36 return 0; 37 }
想法一:首先,考虑暴力的方法,遍历整个序列,假定所有位置都是一个开始位置,然后去求当前开始位置下,任意结束位置的序列和,比较出最大的序列和即可。这样,时间复杂度为O(n^2)
进一步考虑,假设已经得到最大和的子序列,那么之所以这个子序列不包含前面的几个或者后面几个元素的原因,就是因为前面(或者后面)连续几个元素的和是负数。这样,考虑子序列的结束位置,遍历0...n-1,假设当前位置为结束位置,那么如果以前面一个位置为结束的最大子序列和为负数时,只包含当前位置元素的子序列就是以当前位置结束的子序列的最大值;否则,以前面一个位置为结束的最大子序列和加上当前元素就是以当前位置结束的子序列的最大值。这样,按顺序遍历一遍,就可以得到以每个位置为结束位置的最大子序列的和,其中最大的就是整个序列最大子序列的和,时间复杂度O(n)。
想法二:前缀和的想法,首先求出前缀和,一段子序列的和就变成了前缀和序列中两值之差,求出最大的差值即可。就转化成了问题一:如何在O(n)的时间中求出前小后大差值最大的两个数。
1 #include <algorithm> 2 #include <iostream> 3 #include <vector> 4 #include <cstdio> 5 6 using namespace std; 7 8 int readint(){ 9 int x;scanf("%d",&x);return x; 10 } 11 12 int main() 13 { 14 vector<int>a; 15 vector<int>sum; 16 int n,maxn,minn,value_maxn; 17 scanf("%d",&n); 18 for(int i=0;i<n;i++){ 19 a.push_back(readint()); 20 } 21 for(int i=0;i<n;i++){ 22 if(i==0)sum.push_back(a[i]); 23 else sum.push_back(a[i]+sum[i-1]); 24 } 25 for(int i=0;i<n;i++){ 26 if(i==0){ 27 maxn=minn=sum[i]; 28 value_maxn=0; 29 } 30 31 if(sum[i]<minn){ 32 maxn=minn=sum[i]; 33 } 34 if(sum[i]>maxn){ 35 maxn=sum[i]; 36 if(maxn-minn>value_maxn) 37 value_maxn=maxn-minn; 38 } 39 } 40 printf("%d\n",value_maxn); 41 return 0; 42 }
想法:这个问题也有两种做法,1,你可以模仿问题二的第一种做法维护最大最小值。2,模仿问题二的第二个想法,维护前缀积数组。在这里不给出实现。
标签:nbsp 问题 col 小数 main 时间复杂度 开始 最小 cst
原文地址:https://www.cnblogs.com/wz-archer/p/10165117.html