連續子數組的最大和 | 求所有子數組的和的最大值

面試題31:連續子數組的最大和

1.題目描述

輸入一個整型數組,數組裏有正數也有負數。數組中一個或連續的多個整數組成一個子數組。求所有子數組的和的最大值。要求時間複雜度爲O(n)。

例如輸入的數組爲{1,-2,3,10,-4,7,2,-5}和最大的子數組爲{3,10,-4,7,2},因此輸出爲該子數組的和18。

看到這道題,很多人都能想到最直觀的方法,即枚舉出數組的所有子數組並求出它們的和。一個長度爲n的數組,總共有n(n+1/)2個子數組。計算出所有子數組的和,最快也需要O(n^{2})的時間。

2.題目分析

我們試着從頭到尾逐個累加示例數組中的每個數字。初始化和爲0。第一步加上第一個數字1,此時和爲1。接下來第二步加上數字-2,和就變成了-1。第三步加上數字3。我們注意到由於此前累計的和是-1,小於0,那如果用-1加上3,得到的和是2,比3本身還小。也就是說從第一個數字開始的子數組的和會小於從第三個數字開始的子數組的和。因此我們不用考慮從第一個數字開始的子數組,之前累計的和也被拋棄。我們從第三個數字重新開始累加,此時得到的和是3。接下來第四步加10,得到和爲13。第五步加上-4,和爲9。我們發現由於-4是一個負數,因此累加-4之後得到的和比原來的和還要小。因此我們要把之前得到的和
13保存下來,它有可能是最大的子數組的和。第六步加上數字7,9加7的結果是16,此時和比之前最大的和13還要大,把最大的子數組的和由13更新爲16。第七步加上2,累加得到的和爲18,同時我們也要更新最大子數組的和。第八步加上最後一個數字-5,由於得到的和爲13,小於此前最大的和18,因此最終最大的子數組的和爲18,對應的子數組是{3,10,-4,7,2}。整個過程可以用下表總結如下:

3.code

bool g_InvalidInput = false;
    
int FindGreatestSumOfSubArray(int* pData,int nLength)
{
    if((pData == NULL) || (nLength <= 0))    
    {
        g_InvalidInput = true;
        return 0;
    }

    g_InvalidInput = false;

    int nCurSum = 0;//當前子數組的和
    int nGreatestSum = 0x80000000;//最終的子數組的最大和,0x80000000=-(2^31)

    for(int i = 0; i < nLength ; ++i)
    {
        if(nCurSum <= 0)
        {
            nCurSum = pData[i];
        }
        else    nCurSum+=pData[i];

        if(nCurSum > nGreatestSum)    nGreatestSum = nCurSum;
    }

    return nGreatestSum;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章