演算法 求陣列的子陣列之和的最大值

2021-10-25 11:32:23 字數 2624 閱讀 1516

乙個一維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 解法二 思路 我們考慮陣...