乙個一維int陣列,這個陣列有很多子陣列,那麼子陣列之和的最大值是什麼呢?
思考
1、題目說的子陣列是連續的;
2、題目只需要求和,並不需要返回子陣列的具體位置;
3、陣列的元素是整數,所以陣列可能包含有正整數、零、負整數;
舉幾個例子:
陣列:[1, -2, 3, 5, -3, 2]應返回:8
陣列:[0, -2, 3, 5, -1, 2]應返回:9
陣列:[-9, -2, -3, -5, -3]應返回:-2,這也是最大子陣列的和。
【解法一】:
直接的方法,記sum[i,…,j]為陣列a中第i個元素的第j個元素的和(其中0<=i<=jnn):
int
maxsum
(int
* a,
int n)
if(sum > maxmum)
maxmum = sum;}}
return maxmum;
}
如果注意到sum[i,…j] = sum[i,…j-1] + a[j],則可以將演算法中的最後乙個for迴圈省略,避免重複計算,從而使演算法得以改進,改進後的演算法如下,這時複雜度為o(n*n):
int
maxsum
(int
* a,
int n)
if(sum > maxmum)
maxmum = sum;}}
return maxmum;
}
【解法二】:如果將所給陣列(a[0],…,a[n-1])分為長度相等的兩段陣列(a[0],…,a[n/2-1])和(a[n/2],…a[n-1]),分別求出這兩段陣列各自的最大子段和,則原陣列(a[0],…a[n-1])的最大子段和為以下三種情況的最大值:
1、(a[0],…a[n-1])的最大子段和與(a[0],…,a[n/2-1])的最大子段和相同;
2、(a[0],…a[n-1])的最大子段和與(a[n/2],…a[n-1])的最大子段和相同;
3、(a[0],…a[n-1])的最大子段跨過其中兩個元素a[n/2-1]和a[n/2];
第1和2兩種情況事實上是問題規模減半的相同子問題,可以通過遞迴求得。
至於第3中情況,我們只要找到以a[n/2-1]結尾的和最大的一段陣列之和s1 = (a[i],…a[n/2-1])(0 <= i < n/2-1)和以a[n/2]開始和最大的一段陣列之和s2 = (a[n/2],…a[j])(n/2 <= j < n)。那麼第3種情況的最大值為s1 + s2 = a[i]+…+a[n/2-1]+a[n/2]+…+a[j],只須要對原陣列進行一次遍歷即可。
其實這是一種分治演算法,每個問題都可分解成為兩個問題規模減半的子問題,在加上一次遍歷演算法。該分治演算法的時間複雜度滿足典型的分治演算法遞迴式,總的時間複雜度為t(n) = o(n*lgn)。
1、當0 = i = j時,元素a[0]本身構成和最大的一段;
2、當0 =i < j時,和最大的一段以a[0]開始;
3、當0 < i時,元素a[0]跟和最大的一段沒有關係;
從上面三種情況可以看出,可以將乙個大問題(n個元素陣列)轉化為乙個較小的問題(n-1個元素的陣列)。假設已經知道(a[1],…,a[n-1])中和最大的一段陣列之和為all[1],並且已經知道(a[1],…,a[n-1])中包含a[1]的和最大的一段陣列為start[1]。那麼,根據上述分析的三種情況,不難看出(a[0],…,a[n-1])中問題的解all[0]是三種情況的最大值max。通過這樣的分析,可以看出這個問題符合無後效性,可以使用動態規劃的方法來解決。
int max (
int x,
int y)
// 返回x,y中較大值
int maxsum (
int* a,
int n)
return all[0]
;// 遍歷完陣列,all[0]中存放著結果
}
新方法的時間複雜度已經降到o(n)了。
但乙個新的問題出現了:我們額外申請了兩個陣列all、start,能否在空間方面也節省一點呢?
觀察這兩個遞推式:
1 start[i]
= max
;2 all[i]
= max
;
第乙個遞推式:start[i] = max。如果start[i+1] < 0,則start[i] = a[i]。而且,在這兩個遞推式中,其實都只須要用兩個變數就可以了。start[k+1]只有在計算start[k]時使用,而all[k+1]也只有在計算all[k]時使用。所以程式可以進一步改進一下,只需o(1)的空間就足夠了。
int max (
int x,
int y)
int maxsum (
int* a,
int n)
return nall;
}
改進的演算法不僅節省了空間,而且只有寥寥幾行,卻達到了很高的效率。我們還可以換乙個寫法:
int maxsum (
int* a,
int n)
return nall;
}
求陣列的子陣列之和最大值
題目 乙個有n個整數元素的一維陣列a 0.n 1 這個陣列當然有很多子陣列,那麼子陣列之和最大值是多少?解答 求子陣列之和最大,這裡是連續的子陣列,如果乙個數為負數,陣列之和會減少,記住最大值,只要陣列之和沒有小於0就可以繼續累加,比如,3到 1子陣列之和減小了,但是沒有小於0,可以繼續累加下乙個數...
求陣列的子陣列之和的最大值
本題的要求顯然是o n 級的複雜度咯 結合書上的分析,可以發現如下條件 從陣列右邊像左遍歷,當前下標為i,那麼最大值有3中情形 1.最大值為array i 2.最大值為array i maxsuminclude 3.最大值為不包括array i 的maxsumexclude 最後返回最大值 max ...
求陣列的子陣列之和的最大值
乙個有n個整數元素的一維陣列 a 0 a 1 a n 2 a n 1 這個陣列當然有很多子陣列,那麼子陣列之和的最大值是什麼呢?下面將給出3種解法的 解法一 int max maxsum1 int a,int n return maxnum 分析 該演算法的複雜度為o n2 解法二 思路 我們考慮陣...