zoukankan      html  css  js  c++  java
  • #2019121200026 最大子序列和

    题目描述

    给定一段序列,从(a[1])(a[n]),求满足条件的(1leq ileq jleq n),使得(sumlimits^j_{k=i}a[k])最大.

    题解

    1

    最简单最容易想到的就是根据定义来枚举。
    枚举上下界({(i,j) | 1leq ileq jleq n}),维护一个(max)值即可。
    其中枚举上下界的时间复杂度为(O(n^2)),求区间和的复杂度为(O(n)),所以总时间复杂度为(O(n^3))

    for ( int i = 1 ; i <= n ; i++ )
        for ( int j = i ; j <= n ; j++ )
            ans = max(ans,accumulate(a+i,a+j+1,0));
    

    2

    其实就是第一种方法的优化。
    这里有个很容易想到的优化,即预处理出前缀和(sum[i]=sumlimits_{h=1}^ia[h]),算区间和的时候即可将求区间和的复杂度降到(O(1)),枚举上下界的复杂度不变,所以总时间复杂度为(O(n^2))

    for ( int i = 1 ; i <= n ; i++ )
        sum[i]=sum[i-1]+a[i];
    for ( int i = 1 ; i <= n ; i++ )
        for ( int j = i ; j <= n ; j++ )
            ans = max(ans,sum[j]-sum[i-1]);
    

    3

    可以利用动态规划的思维来继续优化,得到一个线性的算法,也是最大连续区间和的标准算法
    定义(maxn[i])为以(i)为结尾的最大连续和,则很容易找到递推关系:(maxn[i]=max {0,maxn[i-1]}+a[i])
    所以只需要扫描一遍即可,总时间复杂度为(O(n))

    for ( int i = 1 ; i <= n ; i++ )
    {
        last = max(0,last)+a[i];
        ans = max(ans,last);
    }
    

    4

    同样用到类似的思维。
    首先也需要预处理出前缀和(sum[i]),可以推出(ans=max {sum[i]-min {sum[j]} | 0leq j<ileq n })
    而最小前缀和可以动态维护,所以总时间复杂度为(O(n))

    for ( int i = 1 ; i <= n ; i++ )
        sum[i]=sum[i-1]+a[i];
    for ( int i = 1 ; i <= n ; i++ )
    {
        ans = max(ans,sum[i]-minn);
        minn = min(minn,sum[i]);
    }
    
    要做就做南波万
  • 相关阅读:
    WIN7右下角的声音图标不见了
    无法解决 equal to 运算中 "Chinese_PRC_BIN" 和 "Chinese_PRC_CI_AS" 之间的排序规则冲突
    查看表空间信息SQL集合
    Oracle分区表
    Oracle数据库的创建、数据导入导出
    Oracle查询出最最近一次的一条记录
    adb命令
    synergy在Windows和ubuntu 多台PC共享一套键盘鼠标
    git add 之后因为没提交正确文件需要撤销
    make clean-kernel && make kernel
  • 原文地址:https://www.cnblogs.com/liuziwen0224/p/12031413.html
Copyright © 2011-2022 走看看