• 算法与数据结构---4.2、最大子段和-枚举优化


    算法与数据结构---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 }

     
  • 相关阅读:
    vue中引用font-awesome
    创建VUE项目
    Core项目添加EF
    DBHelper,之前常用的代码,保存起来。
    appium+python的APP自动化(2)
    appium+python的APP自动化(1)
    单例模式
    双重检测机制解决缓存穿透问题
    mysql数据库
    java的三大特性----封装、集成、多态
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/13023210.html
Copyright © 2020-2023  润新知