• 面试问题之数据结构与算法:最大连续子序列和


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

    给定一个数字序列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;
    }

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

  • 相关阅读:
    wireshark无法捕获无线网卡数据解决办法(failed to set hardware filter to promiscuous mode)
    用PHP检测用户是用手机(Mobile)还是电脑(PC)访问网站
    一次.net Socket UDP编程的10万客户端测试记录
    对象复制
    c#中volatile关键字的作用
    C#操作XML
    ASP.NET AJAX
    C#操作XMl2
    SQLServer 存储过程中不拼接SQL字符串实现多条件查询
    ASP.NET刷新页面的六种方法20081111 22:04asp.net页面刷新重是有问题,收藏几种方法挺有用的.
  • 原文地址:https://www.cnblogs.com/yichengming/p/11469143.html
Copyright © 2020-2023  润新知