輸入乙個整形陣列,求陣列中連續的子陣列使其和最大。比如,陣列x
應該返回 x[2..6]的和187.
我們很自然地能想到窮舉的辦法,窮舉所有的子陣列的之和,找出最大值。
i, j的for迴圈表示x[i..j],k的for迴圈用來計算x[i..j]之和。
maxsofar = 0
for i = [0, n)
forj = [i, n)
sum = 0
for k = [i, j]
sum += x[k]
/* sum is sum of x[i..j] */
maxsofar = max(maxsofar, sum)
有三層迴圈,窮舉法的時間複雜度為o(
n3) o(n3)
我們注意到x[i..j]之和 = x[i..j-1]之和 + x[j]
,因此在j的for迴圈中,可直接求出sum。
maxsofar = 0
for i = [0, n)
sum = 0
for j = [i, n)
sum += x[j]
/* sum is sum of x[i..j] */
maxsofar = max(maxsofar, sum)
顯然,改進之後的時間複雜度變為o(
n2) o(n2)
。在計算fibonacci數時,應該還有印象:用乙個累加陣列(cumulative array)記錄前面n-1次之和,計算當前時只需加上n即可。同樣地,我們用累加陣列cumarr記錄:cumarr[i] = x[0] + . . . +x[i]
,那麼x [i.. j]之和 = cumarr[j] -cumarr[i - 1]
。
cumarr[-1] = 0
for i = [0, n)
cumarr[i] = cumarr[i-1] + x[i]
maxsofar = 0
for i = [0, n)
for j = [i, n)
sum = cumarr[j] - cumarr[i-1]
/* sum is sum of x[i..j] */
maxsofar = max(maxsofar, sum)
時間複雜度依然為o(
n2) o(n2)
。所謂分治法,是指將乙個問題分解為兩個子問題,然後分而解決之。具體步驟如下:
在計算m
c mc
時,注意:mc
mc必定包含總區間的中間元素,因此求mc
mc等價於從中間元素開始往左累加的最大值 + 從中間元素開始往右累加的最大值
。
float maxsum3(l, u)
if (l > u) /* zero elements */
return
0if (l == u) /* one element */
return
max(0, x[l])
m = (l + u) / 2
/* find max crossing to left */
lmax = sum = 0
for (i = m; i >= l; i--)
sum += x[i]
lmax = max(lmax, sum)
/* find max crossing to right */
rmax = sum = 0
for i = (m, u]
sum += x[i]
rmax = max(rmax, sum)
return
max(lmax+rmax,
maxsum3(l, m),
maxsum3(m+1, u));
容易證明,時間複雜度為o(
n∗lo
gn) o(n∗log n)
。kadane演算法又被稱為掃瞄法,該演算法用到了乙個啟發式規則:如果前面一段連續子陣列的和小於0,那麼就丟棄它。其實也蠻好理解的,舉個簡單例子,比如:陣列-1, 2, 3
,-1為負數,為了使得子陣列之和最大,顯然不應當把-1計入進內。
max_ending_here記錄前面一段連續子陣列之和。
initialize:
max_so_far = 0
max_ending_here = 0
loop
foreach element of the array
(a) max_ending_here = max_ending_here + x[i]
(b) if(max_ending_here < 0)
max_ending_here = 0
(c) if(max_so_far < max_ending_here)
max_so_far = max_ending_here
return max_so_far
只遍歷了一遍陣列,因此時間複雜度為o(
n)o(n)
。[1] jon bentley, programming pearls.
[2] geeksforgeeks, largest sum contiguous subarray.
最大和連續子陣列
問題描述 乙個數值型陣列,其子陣列有多個,求其子陣列中最大的和值。所謂和值,是指數組所有元素相加的和。解法 1 掃瞄法,維護max變數,儲存最大和,其初始值為data 0 假設最大和子陣列的第一位下標為i,i從0到n 1,對於每個i值,從data i 開始,進行累加,每加乙個數,與max變數比較一次...
連續子陣列最大和
hz偶爾會拿些專業問題來忽悠那些非計算機專業的同學。今天測試組開完會後,他又發話了 在古老的一維模式識別中,常常需要計算連續子向量的最大和,當向量全為正數的時候,問題很好解決。但是,如果向量中包含負數,是否應該包含某個負數,並期望旁邊的正數會彌補它呢?例如 連續子向量的最大和為8 從第0個開始,到第...
連續子陣列最大和
求乙個陣列的連續的子陣列的最大和。例如 連續子向量的最大和為8 從第0個開始,到第3個為止 思路 對於每個元素,有兩種可能,一是加入到原來的子陣列成為新的一員 二是自己成為新子陣列的開頭,這兩種情況應該怎樣判斷呢 如果當前元素加入到子串行中,求和的結果比自己的值還小,那麼就自己成為新子串行的開頭 即...