最大子串行和問題

2021-08-09 02:51:19 字數 3245 閱讀 8702

給定k個整數組成的序列

,連續子列被定義為

其中 1≤

i≤j≤

k 。「最大子列和」則被定義為所有連續子列元素的和中最大者。例如給定序列

,其連續子列

有最大的和

20 。現要求你編寫程式,計算給定整數序列的最大子列和。

本題旨在測試各種不同的演算法在各種資料情況下的表現。各組測試資料特點如下:

輸入格式:

輸入第1行給出正整數k (≤100000);第2行給出k個整數,其間以空格分隔。

輸出格式:

在一行中輸出最大子列和。如果序列中所有整數皆為負數,則輸出0。

輸入樣例:

6 -2 11 -4 13 -5 -2

輸出樣例:

20問題分析:

首先最樸素的方法是暴力求解o(

n3)

直接兩個for迴圈枚舉子序列的首尾,然後再來個迴圈計算序列的和,每次更新和的最大值。但是這種方法的複雜度是o(

n3) ,效率太低了。

第二種方法是預處理o(

n2)

在讀入的時候將前面數的和放在陣列中,就能得到乙個陣列su

m[i]

儲存前i個數的和。然後兩重迴圈列舉首尾,利用su

m 陣列迅速求出子串行的和。其實這種方法只是優化了前面那種方法的計算和的迴圈,複雜的是o(

n2) 。

第三種是利用分治思想o(

nlog

n)分治演算法看**不是很好理解,其實思想很簡單,就是把序列分成兩塊計算,用遞迴分別求出兩塊序列中的最大子串行和,然後從序列中間向兩邊遍歷求出包含中心的序列的最大和。返回最大的那個序列和。

用分治演算法的複雜度好了一些,是o(

nlog

n),雖然不是最優解,但是理解這種演算法的確能讓我們對遞迴理解得更加深刻。

第四種是累積遍歷演算法o(

n)遍歷序列的時候對sum進行累計,如果sum累積後小於0的話就把sum重置為負無窮,每次更新sum的最大值。最後便能求出最大值。

其實這個演算法就是把序列分為好幾塊,每一塊滿足:對於任意k,前k個數的和不會小於0(小於0就會**成兩塊了),當前i個數的和大於最大值時就進行更新,而最大值的左邊界就是該塊序列的第乙個,右邊界是第i個。時間複雜度為o(n),而且可以一邊讀取一邊處理,不需要開闢陣列來存,空間也很省。

第五種是動態規劃o(

n)dp做法是很普遍的做法,只要想出狀態轉移方程就可以很快做出來了。

狀態轉移方程:su

m[i]

=max

. (su

m[i]

記錄以a[

i]為子串行末端的最大連續和。)在dp的過程中便可以更新su

m 陣列的最大值以及兩個邊界。

其實完全可以不用陣列,累計su

m 直到su

m+a<

a ,把su

m 賦值為

a ,更新最大值就行了。你會發現這跟第4種方法是一樣的。。。只是判斷條件不一樣,乙個是su

m<=

0乙個是su

m+a<

a 。(其實是一樣的)所以複雜度和第四種是一樣的都是o(n)。

暴力求解

int maxsubseqsum1( int a, int n )

/* j迴圈結束 */

} /* i迴圈結束 */

return maxsum;

}

預處理

int maxsubseqsum2( int a, int n )

/* j迴圈結束 */

} /* i迴圈結束 */

return maxsum;

}

分治思想

int max3( int a, int b, int c )

int divideandconquer( int list, int left, int right )

/* 下面是"分"的過程 */

center = ( left + right ) / 2; /* 找到中分點 */

/* 遞迴求得兩邊子列的最大和 */

maxleftsum = divideandconquer( list, left, center );

maxrightsum = divideandconquer( list, center+1, right );

/* 下面求跨分界線的最大子列和 */

maxleftbordersum = 0; leftbordersum = 0;

for( i=center; i>=left; i-- ) /* 左邊掃瞄結束 */

maxrightbordersum = 0; rightbordersum = 0;

for( i=center+1; i<=right; i++ ) /* 右邊掃瞄結束 */

/* 下面返回"治"的結果 */

return max3( maxleftsum, maxrightsum, maxleftbordersum + maxrightbordersum );

}int maxsubseqsum3( int list, int n )

累積遍歷演算法

int maxsubseqsum4( int a, int n )

return maxsum;

}

動態規劃演算法

sum←(-∞)  

max←(-∞)

for i←1 to len do

if sum+arr[i]else

sum←sum+arr[i]

end if

if maxif

end for

return max

最大子串行和問題

問題 給定一整數序列a1,a2,an 可能有負數 求a1 an的乙個子串行ai aj,使得ai到aj的和最大 例如 整數序列 2,11,4,13,5,2,5,3,12,9的最大子串行的和為21。對於這個問題,最簡單也是最容易想到的那就是窮舉所有子串行的方法。利用三重迴圈,依次求出所有子串行的和然後取...

最大子串行和問題

問題描述 給定乙個整數序列 可能有負數 求一子串行 記為l 使得該子串行所有元素之和最大。例 給定序列 2,11,4,13,5,2,則最大子串行和為20 11,4,13 方法一 遍歷窮舉 o n 2 略方法二 分治遞迴 o n logn 思路 將輸入序列l分為左右兩個子串行l1和l2,則l 只可能以...

最大子串行和問題

問題描述 求 2,11,4,13,5,2 的最大子串行和。方法一 使用3層for迴圈巢狀,窮舉式的嘗試所有的可能,如下 public class demo1 return maxsum public static void main string args system.out.println 最大...