求子数组的最大和

来源:互联网 发布:淘宝设置自动发货 编辑:程序博客网 时间:2024/06/05 01:10

题目要求如下:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为 O(n)。
例如输入的数组为 1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为 3, 10, -4, 7, 2,
因此输出为该子数组的和 18。

这个问题还是来自July微软面试100题序列,我的解题思路如下:
要求最大子数组之和,可以这样想:最大的子数组和可以有两部分构成:当前最大子数组和A、刚加入的一个元素b。先将这两部分加起来,作为临时的当前最大子数组和B,如果B>A,那么肯定要将b作为最大子数组的新元素,但是因为B = A + b,所以B>A完全可能只是因为b>A,而当前最大子数组和A也可能是一个负数,充当了减小即将获得的最大子数组和的角色,这时候当然要舍弃之前的最大子数组和序列,而从元素b开始收集最大子数组和序列;如果A为正的话,最大子数组只需扩张,把b加进来即可。如果B <=A,此时不能随便把b抛弃,因为后续的元素累加起来时,会使整个子数组的和增大,这时候的思想是把b加到b后面的元素上去,一起作为即将加入的一个元素,如此循环,就可以实现O(n)复杂度的最大子数组和求解。总之关键点在于(1)在B = A + b这个等式中A与b是处在同等重要的位置,(2)b可能是一个元素,也可能是某几个元素的和,用一种整体的思想看来待b。

#include "stdafx.h"#include <iostream>using namespace std;//start、end记录了最大子数组在原数组中的区间int GetMaxSubSequence(int* arrays,int n,int &start,int &end){    int curMaxSum = INT_MIN;  //相当于A,最开始的时候初始化为最小整数    start = -1;    end = -1;    int tempTotal = 0;  //相当于b    for (int i = 0; i < n; ++i)    {        tempTotal += arrays[i];        //total相当于B        int total = tempTotal + curMaxSum;        if(total > curMaxSum)        {            if(arrays[i] > total)            {                start = i;                end = i;                curMaxSum = arrays[i];            }            else            {                end = i;                curMaxSum += tempTotal;            }            tempTotal = 0;        }    }    return curMaxSum;}int _tmain(int argc, _TCHAR* argv[]){    int arrays[] = {1, -2, 3, 10, -4, 7, 2, -5};    int start = 0,end = 0;    int maxVal = GetMaxSubSequence(arrays,8,start,end);    cout<<maxVal<<endl;    for (int i = start; i <= end;++i)    {        cout<<arrays[i]<<' ';    }    cout<<endl;    return 0;}

程序运行截图:
这里写图片描述
July给出的答案里指出这是一个传统的的贪心问题,我不太懂贪心算法,以后肯定要探索的,这里想强调的是一种整体思想(对于b的处理),而实际编码结果与July的大同小异。

0 0