zoukankan      html  css  js  c++  java
  • 最大连续区间和

    问题概述

    这是一个经典的问题。

    给定一个长度为n的序列a[1],a[2]...a[n-1],a[n]

    求一个连续的子序列 a[i],a[i+1]...a[j-1],a[j],使得a[i]+a[i+1]...a[j-1]+a[j]最大。

    暴力的方法就是双重循环枚举左右端点,然后直接找最大的就好了。 但是算法的复杂度是 O(N^2) 不够优秀

     

    动态规划解法  复杂度O(n) 

    我们让 dp[ i ] 代表以 a[ i ] 为结束的最大连续子段和

    因为是以a[ i ]为结束且是连续子段  那么

    dp[ i ] 要么就是  a[ i ]本身

              要么 就是a[ i ] + 以a[ i-1 ]为结束的最大连续字段和  也就是 a[ i ] + dp[ i - 1 ]

    所以 状态转移方程出来了      dp[i] = max( A[i], dp[i-1]+A[i] )

    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);//输入
        dp[0]=0;
        for(int i=1;i<=n;i++){//状态转移方程
            dp[i]=max(a[i],dp[i-1]+a[i]);
        }
        ll maxn=0;
        for(int i=1;i<=n;i++){//遍历找最大值
            maxn=max(dp[i],maxn);
        }
        printf("%lld
    ",maxn);
    }

    这个算法的常数还是比较大的,我们可以优化下常数

    ll a[maxn];
    ll n,ans,dp;
    int main(){
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            dp=max(a[i],dp+a[i]);
            ans=max(dp,ans);
        }
        printf("%lld
    ",ans);
    }

    如果我们还想知道这个具体的最大连续区间的左右端点是什么

     1 int a[maxn];
     2 int main() {
     3     //freopen("../in.txt","r",stdin);
     4     int t;
     5     scanf("%d",&t);
     6     int num = 1;
     7     while (t--) {
     8         int n;
     9         scanf("%d",&n);
    10         int ans = -INF,dp = 0,l = 1,r = 1,k = 1;
    11         for (int i = 1;i <= n;i++) {
    12             scanf("%d",&a[i]);
    13             if (dp >= 0) {
    14                 dp += a[i];
    15             }
    16             else {
    17                 dp = a[i];
    18                 k = i;
    19             }
    20             if (dp > ans) {
    21                 ans =  dp;
    22                 l = k;
    23                 r = i;
    24             }
    25         }
    26         printf("Case %d:
    ",num++);
    27         printf("%d %d %d
    ",ans,l,r);
    28         if (t != 0)
    29             printf("
    ");
    30     }
    31     return 0;
    32 }
  • 相关阅读:
    Oracle学习笔记:使用replace、regexp_replace实现字符替换、姓名脱敏
    Oracle学习笔记:外连接(+)的用法
    Oracle学习笔记:with as子查询用法
    Oracle学习笔记:a inner join b与from a,b where a.x=b.x的差异
    oracle查看表,索引,视图,存储过程的定义
    oracle查看监听状态
    由sock引起的感想
    xargs
    oracle知识点小结1
    Oracle系统权限列表
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12180830.html
Copyright © 2011-2022 走看看