31. 連續子數組的最大和

題目描述

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

解析

1. 解法一:
看到這個題目,我們首先想到的是求出這個整型數組所有連續子數組的和,長度爲n的數組一共有 n(n+2)/2個子數組,因此要求出這些連續子數組的和最快也需要O(n^2)的時間複雜度。但是題目要求的O(n)的時間複雜度,因此上述思路不能解決問題。
2. 解法二:
看到O(n)時間複雜度,我們就應該能夠想到我們只能對整個數組進行一次掃描,在掃描過程中求出最大連續子序列和以及子序列的起點和終點位置。假如輸入數組爲{1,-2,3,10,-4,7,2,-5},我們嘗試從頭到尾累加其中的正數,初始化和爲0,第一步加上1,此時和爲1,第二步加上-2,此時和爲-1,第三步加上3,此時我們發現-1+3=2,最大和2反而比3一個單獨的整數小,這是因爲3加上了一個負數,發現這個規律以後我們就重新作出累加條件:如果當前和爲負數,那麼就放棄前面的累加和,從數組中的下一個數再開始計數。
3. 解法三:應用動態規劃法
這裏寫圖片描述

主要代碼實現

int FindgGreatestOfSubArray(int* pData, int nLength){
    //傳參有效性檢測
    if(pData == NULL || nLength <= 0){
        return 0;
    }
    int nCurSum = 0;
    int nGreatestSum = 0;

    for(int i=0; i<nLength; i++){
        if(nCurSum < 0)
            nCurSum = pData[i];     //拋棄i下標之前的數組元素
        else
            nCurSum += pData[i];
        if(nCurSum > nGreatestSum)
            nGreatestSum = nCurSum;

    }
    return nGreatestSum;
}

測試用例

// ====================測試代碼====================
void Test(char* testName, int* pData, int nLength, int expected, bool expectedFlag)
{
    if(testName != NULL)
        printf("%s begins: \n", testName);

    int result = FindgGreatestOfSubArray(pData, nLength);
    if(result == expected && expectedFlag == g_InvalidInput)
        printf("Passed.\n");
    else
        printf("Failed.\n");
}

// 1, -2, 3, 10, -4, 7, 2, -5
void Test1()
{
    int data[] = {1, -2, 3, 10, -4, 7, 2, -5};
    Test("Test1", data, sizeof(data) / sizeof(int), 18, false);
}

// 所有數字都是負數
// -2, -8, -1, -5, -9
void Test2()
{
    int data[] = {-2, -8, -1, -5, -9};
    Test("Test2", data, sizeof(data) / sizeof(int), -1, false);
}

// 所有數字都是正數
// 2, 8, 1, 5, 9
void Test3()
{
    int data[] = {2, 8, 1, 5, 9};
    Test("Test3", data, sizeof(data) / sizeof(int), 25, false);
}

// 無效輸入
void Test4()
{
    Test("Test4", NULL, 0, 0, true);
}

int main(void)
{
    Test1();
    Test2();
    Test3();
    Test4();
    system("pause");
    return 0;
}

改進

保存最大和對應的子數組:修改上面的主要代碼,當重置當前數組和的時候,記錄起始數組下標,修改數組最大值的時候,記錄當前最大值的數組下標。(在函數中採用引用傳遞參數,第一次使用引用變量)

int FindgGreatestOfSubArray(int* pData, int nLength, int& a, int& b){
    //傳參有效性檢測
    if(pData == NULL || nLength <= 0){
        g_InvalidInput = true;
        return 0;
    }
    int nCurSum = 0;
    int nGreatestSum = 0;

    for(int i=0; i<nLength; i++){
        if(nCurSum < 0){
            nCurSum = pData[i];     //拋棄i下標之前的數組元素
            a = i;
        }
        else
            nCurSum += pData[i];
        if(nCurSum > nGreatestSum){
            nGreatestSum = nCurSum;
            b = i;
        }
    }
    return nGreatestSum;
}

參考博文

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

發佈了115 篇原創文章 · 獲贊 9 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章