连续子数组的最大和问题及其变化

输入一个整型数组,数组中有正数也有负数。数组中的一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。

如输入{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},输出应该是18

这是在《剑指offer》上看到的题目,这道题可以在O(n)的时间复杂度内求解,而且这个问题可以是很多更加复杂问题的子问题。所以记录加深下印象。

分析:

以上面列出的{1,-2,3,10,-4,7,2,-5}来分析,可以这么想,从头开始遍历,当前面某几项的和是负数,需要舍弃前面的。

即从1开始,此时记录到的最大和为1,然后遍历到-2,因为1+(-2)<0,所以舍弃掉-2,然后继续向后分析,3>1,所以更新最大值为3,然后继续向后遍历,3+10=13,更新最大值为13,13+(-4)=9,继续向后遍历。。。

即用两个中间变量来存储,一个用来存储遍历到当前项时最大的连续子数组之和(maxSum),另外一个用来存储包含当前项的最大子数组之和(curSum),如果curSum>maxSum,那么用curSum更新maxSum,否则继续遍历。

代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
//输入是否正确的标示符
bool f_validate=true;

int getGreatestOfSubArray(int *datas,int length)
{
    if(datas==NULL|| length<=0)
    {
        f_validate=false;
        return 0;
    }       

    int curSum=0;
    int maxSum=0x80000000;//0x80000000是最小的负整数

    for(int i=0;i<length;i++)
    {
        //如果当前和小于等于0,那么舍弃掉它,从数组中的当前项开始累加
        if(curSum<=0)
        {
            curSum=datas[i];
        }else//否则当前和需要加上数组中的当前的项
        {
            curSum+=datas[i];
        }

        //每次计算一次当前的和后都需要更新最大和
        if(curSum>maxSum)
                maxSum=curSum;
    }

    return maxSum;
}

int main(){
    int datas[]={1,-2,3,10,-4,7,2,-5};
    int max;max=getGreatestOfSubArray(datas,sizeof(datas)/sizeof(datas[0]));
    std::cout<<max<<std::endl;
    return 0;
}

之前还没注意,后来看了书之后发现可以用动态规划来分析这个问题:

设f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求的是max{f(i)},0<=i

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
/*计算从first到last,包括first和last之间的差的最大和*/
int getGreatest(int *datas,int first,int last);

int getGreatestSubOfArray(int * datas,int length)
{
    if(datas==NULL||length<=0) return -1;
    int curSum=0;
    int maxSum=0;
    //分割,将数组以一个基准点分割成两部分,分别求两个部分的最大和,然后再求总的最大和
    for(int i=1;i<length-2;i++)
    {
        curSum=getGreatest(datas,0,i)+getGreatest(datas,i+1,length-1);
        if(curSum>maxSum)
        {
                maxSum=curSum;
        }
    }
    return maxSum;

}

/*计算从first到last,包括first和last之间的差的最大和*/
int getGreatest(int *datas,int first,int last)
{
    if(datas==NULL||first<0||last<0||first>=last) return -1;
    int curSum=0;
    int maxSum=0;
    for(int i=first;i<last;i++)//从first到last依次遍历,计算相邻两项之间的差值,转换成了连续数组的最大和问题
    {
            if(curSum<=0)//如果当前和小于0,丢弃它
            {
                curSum=datas[i+1]-datas[i];
            }else//否则加上当前项
            {
                curSum+=datas[i+1]-datas[i];
            }

            if(curSum>maxSum)//更新最大值
            {
                maxSum=curSum;
            }
    }
    return maxSum;

}

int main(){
    int datas[]={1,4,5,2,3,1};
    int max=getGreatestSubOfArray(datas,sizeof(datas)/sizeof(datas[0]));
    std::cout<<max<<std::endl;
    return 0;
}
时间: 2024-10-06 17:17:13

连续子数组的最大和问题及其变化的相关文章

一个数组中连续子数组的最大和

//连续子数组的最大和     //{ 1, -2, 3, 10, -4, 7, 2, -5 };//最大子数组18     #include<iostream>     using namespace std;     bool g_InValid = false;     int FindGreatSumOfSubArray(int* arr, int size)     {     if (arr == NULL || size <= 0)     g_InValid = true

编程算法 - 连续子数组的最大和 代码(C)

连续子数组的最大和 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 输入一个整型数组, 数组里有正数也有负数. 数组中一个或连续的多个整数组成一个子数组.求所有子数组的和的最大值. 使用一个数保存当前和, 如果当前和为小于0,  则替换新值, 否则, 递加, 使用一个数保存临时最大值. 代码: /* * main.cpp * * Created on: 2014年6月29日 * Author: wang */ #include <stdio

求数组中连续子数组的最大和

问题: 求解数组中连续一段子数组和的最大值.例如:{31,-41,59,26,-53,58,97,-93,-23,84},最大值为59+26-53+58+97=187 思路: 计算出任意i到j之间连续子数组的和再比较必然能得到最大值,但时间复杂度为O(n^2),我们希望能找出线性时间的算法. 我们注意到,假如数组中全为正数,那么最大和必然为全部数相加:如果数组中有负数,并且如果加上某个负数,子数组的和小于0,则最大和子数组必然不包含这个负数. 基于此,给出以下代码: //计算数组中任何连续子数组

【原题】求两个不相交的连续子数组的最大和

题目: 有一个整数数组n,a和b是n里两个互不相交的子数组.返回sum(a)+sum(b)的最大值. 分析: 新建两个数组left和right,left[i]表示n[0:i]的连续子数组的最大和,right[i]表示n[i:length-1]的连续子数组的最大和.left[i]+right[i+1]的最大值就是答案. int SumOfTwoSubarray(const vector<int> &n) { if (n.size() < 2) { throw exception()

剑指Offer面试题:28.连续子数组的最大和

一.题目:连续子数组的最大和 题目:输入一个整型数组,数组里有正数也有负数.数组中一个或连续的多个整数组成一个子数组.求所有子数组的和的最大值.要求时间复杂度为O(n).例如输入的数组为{1,-2,3,10,-4,7,2,-5},和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和18. 这个题目在我去年参加校园招聘时,某公司的二面采用了机试,而题目刚好就是这道题.一般看到这道题目就会想到枚举出数组的所有子数组并求出它们的和.一个长度为n的数组,总共有n(n+1)/2个子数组.计算

Task 4 求数组的连续子数组的最大和(团队合作)

小组成员:李敏.刘子晗 1.设计思想:由于已经做过这个题目,只要对之前的程序加上相应的测试和约束即可.我们两个人一起商议后,决定了程序的主框架和并列出了最终可以实现的功能.先要定义数组长度和上下限的变量,然后通过if语句对用户所给出的长度和数值进行判断看是否合法,如果不合法要重新输入.最后再加上之前求和的相应代码即可. 2.出现的问题:我们达成协议后,李敏负责编程,我负责测试.开始写程序,在写判断数值是否满足int整型范围的时候出现了错误,我在测试的时候发现她把小于号错写成了大于号,然后加以改正

剑指OFFER之最大子向量和(连续子数组的最大和)(九度OJ1372)

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

剑指offer面试题31连续子数组的最大和

一.题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止).你会不会被他忽悠住? 二.解题思路 求连续子数组的最大和,首先想的到最笨的方法就是暴力解决,两个for循环,遍历数组找到和最大的子

连续子数组的最大和-剑指Offer

连续子数组的最大和 题目描述 输入一个整数数组,数组里有整数也有负数.数组中一个或连续的多个整数组成一个数组.求所有子数组的和的最大值.要求时间复杂度为O(n) 思路 我们可以举例分析数组的规律,用一个变量来存储最大值,另一个变量存储当前的和,若当前和为负值,则后面加的和都会比当前的小,所以当为负值时把当前的和设置为0重新开始计算 我们也可以通过动态规划的方法来解决这个问题 代码 public class Solution { public int FindGreatestSumOfSubArr