【July程序员编程艺术】之最大字段和问题

题目描述:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。

我的解题思路:
现在拿到这一类字符串或者数组的题目,我的第一反应就是先举个例子,想想最笨的解法,然后再去想办法进行更改进。针对上述给出的例子,最直接的想法自然是找出所有的子串。起始元素和子串的长度决定着一个子串,如1开始的子串,长度可以为1-8,一共8个。这种算法是最直观的,时间复杂度是O(N*N*N)。

接下来就要想办法去改进。改进的大思路也很明确:在连续的for循环操作之间建立联系,使得上一次操作的结果可以应用于下一次。针对这个问题,从最简单的情况入手,首先取-5作为子串的起始元素,这时候子串只有一个-5.接下来就是取2位子串的起始元素,这时候,子串长度可以为1或者2.以2为起始元素的子串的和可以视为:max(2+0,2+max(-5)):即要么是元素2自己构成子串,要么是元素2加上以-5开始的sum最大的子串构成新的子串。这样一来,就可以用到动态规划的思路,递归的定义最优值,以自底向上的方式计算出最优值。最后写的程序如下:

#include <iostream>
using namespace::std;

void update_tmp(int * src,int i,int len,int * tmp,int max)
{
    int curr_len=len-i;
    int pri_len=curr_len-1;
    int tmp_max = 0;
    for(int j=pri_len-1;j>=0;j--)
    {
        tmp[j+1]=src[i]+tmp[j];

    }
        tmp[0]=src[i];



}
void main()
{
    //int src[]={1,-2,3,10,-4,7,2,-5};
    int src[] = {-1,-2,-3,-4};
    int len = sizeof(src)/sizeof(int);

    int tmp_max= src[len-1];//存储最后一个元素
    int curr_max= src[len-1];
    for(int i=len-2;i>=0;i--)
    {
        if(tmp_max>0)
        {
            tmp_max=src[i]+tmp_max;

        }
        else
        {
            if(tmp_max<src[i])
                tmp_max=src[i];
        }
        if(tmp_max>curr_max)
            curr_max=tmp_max;
    }
 cout << curr_max << endl;

}

其实一开始并没有想到DP的算法,但是写完程序再看看博客,才发现所用的就是动态规划的思想。 博客中所给的算法也是用的动态规划的思想,只是博客中是固定末尾元素,我的程序是固定起始元素而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值