題目:
輸入一個整形數組,數組裏有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。求所有子數組的和的最大值。
例如輸入的數組爲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;
}