求最大子數組和

題目:

輸入一個整形數組,數組裏有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。求所有子數組的和的最大值。

例如輸入的數組爲1, -2, 3, 10, -4, 7, 2, -5,和最大的子數組爲3, 10, -4, 7, 2,因此輸出爲該子數組的和18。
如果不考慮時間複雜度,我們可以枚舉出所有子數組並求出他們的和。由於長度爲n的數組有O(n2)個子數組;而且求一個長度爲n的數組的和的時間複雜度爲O(n)。因此這種思路的時間是O(n3)。
當我們加上一個正數時,和會增加;當我們加上一個負數時,和會減少。如果當前得到的和是個負數,那麼這個和在接下來的累加中應該拋棄並重新清零,不然的話這個負數將會減少接下來的和。

     有了前面的思想之後,很顯然我們需要知道一個數組的起始點和終結點。直接先上代碼,再解釋。

在下面這個函數MaxSum()中,先定義首位變量標記子數組的前後位;然後從左到右開始搜索數組的每個元素。

現在舉例 -1,4,3,3,4,-1,-5,-2,8,1來說明;

i = 0,sum = 0,此時執行else後一條語句使sum=-1。接着,由於sum>max,重新給max賦值使max = -1,重新臨時標記數組左下標和右下標;

i = 1,sum=4,此時左下標重新被標記爲當前搜索的元素下標。由於sum>max,重新給max賦值使max = 4,重新臨時標記數組左下標和右下標;

i = 2,sum=7,由於sum>max,重新給max賦值使max = 7,重新臨時標記數組左下標和右下標,此時右下標爲當前搜索元素的下標;

i = 3,sum=10,由於sum>max,重新給max賦值使max = 10,重新臨時標記數組左下標和右下標,此時右下標爲當前搜索元素的下標;

i = 4,sum=14,由於sum>max,重新給max賦值使max = 14,重新臨時標記數組左下標和右下標,此時右下標爲當前搜索元素的下標;

i = 5,sum=13,由於sum<max,進行下一個循環;

i = 6,sum=8,由於sum<max,進行下一個循環;

i = 7,sum=6,由於sum<max,進行下一個循環;

i = 8,sum=14,由於sum=max,進行下一個循環;

i = 9,sum=15,由於sum>max,重新給max賦值使max = 14,重新臨時標記數組左下標和右下標,此時右下標爲當前搜索元素的下標;

#include<cstdio>
int MaxSum(int *a , int n)
{
    int tempstart = 0 , sum=0 , max = -1000;
    int i , start , end;
    start = end = 0;
    for(i = 0 ; i < n ; i++)
    {
        if(sum < 0)
        {
            sum = a[i];
            tempstart = i;
        }
        else
            sum += a[i];
        if(sum > max)
        {
            max = sum;
            start = tempstart;
            end = i;
        }
    }
    return max;
}

int main(){
	int m[10];
	for(int i = 0;i < 10;i ++)
		scanf("%d",&m[i]);
	printf("%d\n",MaxSum(m,10));
	return 0;
}


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