连续子数组的最大和

来源:互联网 发布:淘宝试用联盟网 编辑:程序博客网 时间:2024/05/05 07:33

题目描述

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)

/*动态规划的思想当前面的k-1个连续序列大于0,对序列和有贡献,则到第k个数的时候,最大和sum为前面的k-1个数之和temsum加上第k个数当前k-1个数之和小于0时,如果直接加上第k个数,会使总和变小,所以直接令temsum等于第k个数重新累计序列和*/class Solution {public:    int FindGreatestSumOfSubArray(vector<int> array) {         if(array.size()==0) return 0;        int sum=array[0],temsum=sum;        //令其初始值为第一个数,而不设置为0,防止序列全为负数时出现最后最大值为0,而不是为负数的错误输出        for(int i=1; i<array.size(); ++i)            {            temsum=(temsum>0) ? (temsum+array[i]) : array[i];            //首先要明白的是一个序列之和为正数,才会在与一个数相加时使总和增加            //保证前k-1个数之和为非负数,然后用temsum保存可能最大和            sum=(temsum>sum) ? temsum : sum;                //第k个数可正可负,当第k个数为负数时,最大值有可能为前k-1个数之和,所以用sum和temsum比较之后保存最大值        }        return sum;    }};

对于这个问题,题目只要求输出找到的序列和的最大值,那如果要求输出这个序列呢?

经过进一步思考,其实也很简单,用中间变量记录一下序列的起始位置就行:

class Solution {public:    int FindGreatestSumOfSubArray(vector<int> array, vector<int>& maxarray) {         if(array.size()==0) return 0;        int sum=array[0],temsum=sum;        int start=0,temstart=0,end=0,temend=0;        for(int i=1; i<array.size(); ++i)            {            if(temsum>0)                {                temsum+=array[i];                temend=i;            }            else{                temsum=array[i];                temstart=i;            }            if(temsum>sum)                {                sum=temsum;                start=temstart;                end=temend;            }        }        for(int i=start;i<=end;++i)            maxarray.push__back(array[i]);        return sum;    }};