zoukankan      html  css  js  c++  java
  • 面试问题之数据结构与算法:最大连续子序列和

    最大连续子序列和问题如下:

    给定一个数字序列A1,A2,...,An,求i,j(1<=i<=j<=n),使得Ai+...+Aj最大,输出这个最大和。

    样例:

    -2  11  -4  13  -5  -2

    显然11+(-4)+13=20为和最大的选取情况,因此最大和为20

    下面介绍动态规划的做法,复杂度为O(n)。

    步骤1:令状态dp[i]表示以A[i]作为末尾的连续序列的最大和(这里是说A[i]必须作为连续序列的末尾)

    步骤2:做如下考虑:因为dp[i]要求是以A[i]结尾的连续序列,那么只有两种情况:

      1、这个最大和的连续序列只有一个元素,即以A[i]开始,以A[i]结尾。

      2、这个最大和的连续序列有多个元素,即从前面某处A[p]开始(p<i),一直到A[i]结尾。

    对于第一种情况,最大和就是A[i]本身。

    对于第二种情况,最大和是dp[i-1]+A[i]。

    于是得到状态转移方程:

        dp[i]=max{A[i],dp[i-1]+A[i]}

    这个式子只和i与i之前的元素有关,且边界为dp[0]=A[0],由此从小到大枚举i,即可得到整个dp数组。接着输出dp[0],dp[1],...,dp[n-1]中的最大值即为最大连续子序列的和。

    代码如下:

    /*
        最大连续子序列和 
    */
    
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <stdlib.h>
    #include <time.h>
    #include <stdbool.h>
    
    #define maxn 10010
    int A[maxn], dp[maxn];    // A[i] 存放序列,dp[i] 存放以 A[i] 为结尾的连续序列的最大和 
    
    // 求较大值
    int max(int a, int b) {
        return a>b ? a : b; 
    } 
    
    int main() {
        int n, i, k;
        scanf("%d", &n);
        for(i=0; i<n; ++i) {        // 输入序列 
            scanf("%d", &A[i]);
        }
        dp[0] = A[0];                // 边界
        for(i=1; i<n; ++i) {
            // 状态转移方程 
            dp[i] = max(A[i], dp[i-1] + A[i]);
        } 
        // 求最大连续子序列和 
        k = dp[0];
        for(i=1; i<n; ++i) {
            if(dp[i] > k) {
                k = dp[i];
            }
        }
        printf("%d
    ", k);        // 输出 
    
        return 0;
    }

    状态的无后效性是指:当前状态记录了历史信息,一旦当前状态确定,就不会再改变,且未来的决策只能在已有的一个或若干个状态的基础上进行,历史信息只能通过已有的状态去影响未来的决策。

  • 相关阅读:
    增强遍历和Object多参数遍历
    Git忽略规则(.gitignore配置)不生效原因和解决
    算法基本概念及常用算法Python实现
    使用GitBook编写项目文档
    Python 闭包
    Linux 进程管理
    Kafka 安装及入门
    IP地址0.0.0.0表示什么
    Docker 入门
    Docker Linux下安装
  • 原文地址:https://www.cnblogs.com/yichengming/p/11469143.html
Copyright © 2011-2022 走看看