最大子串行和問題

2021-06-05 15:05:33 字數 1815 閱讀 5826

問題: 

給定一整數序列a1, a2,... an (可能有負數),求a1~an的乙個子串行ai~aj,使得ai到aj的和最大 

例如:整數序列-2, 11, -4, 13, -5, 2, -5, -3, 12, -9的最大子串行的和為21。對於這個問題,最簡單也是最容易想到的那就是窮舉所有子串行的方法。利用三重迴圈,依次求出所有子串行的和然後取最大的那個。當然演算法複雜度會達到o(n^3)。

int maxsubsum1(int a,int size ) 

return maxsum;

}

這個演算法很簡單,i表示子串行起始下標,j表示子串行結束下標,遍歷子串行的開頭和結束下標,計算子串行的和,然後判斷最大子串行。很明顯的看出演算法複雜度是o( pow( n, 3 ) )

顯然這種方法不是最優的,下面給出乙個演算法複雜度為o(n)的線性演算法實現,演算法的**於programming pearls一書。在給出線性演算法之前,先來看乙個對窮舉演算法進行優化的演算法,它的演算法複雜度為o(n^2)。其實這個演算法只是對對窮舉演算法稍微做了一些修改:其實子串行的和我們並不需要每次都重新計算一遍。假設sum(i, j)是a[i] ... a[j]的和,那麼sum(i, j+1) = sum(i, j) + a[j+1]。利用這乙個遞推,我們就可以得到下面這個演算法: 

int max_sub(int a,int size)

}  return max;

}

那怎樣才能達到線性複雜度呢?這裡運用動態規劃的思想。先看一下源**實現:

int max_sub2(int a, int size)

return max;

}

在這一遍掃瞄陣列當中,從左到右記錄當前子串行的和temp_sum,若這個和不斷增加,那麼最大子串行的和max也不斷增加(不斷更新max)。如果往前掃瞄中遇到負數,那麼當前子串行的和將會減小。此時temp_sum 將會小於max,當然max也就不更新。如果temp_sum降到0時,說明前面已經掃瞄的那一段就可以拋棄了,這時將temp_sum置為0。然後,temp_sum將從後面開始將這個子段進行分析,若有比當前max大的子段,繼續更新max。這樣一趟掃瞄結果也就出來了。 

分治法:最大子串行和可能出現在三個地方:整個出現在輸入資料的左半部分,整個出現在輸入資料的右半部分,或者跨越輸入資料的中部從而佔據左右兩個半部分。

/**

* recursive maximum contiguous subsequence sum algorithm.

* finds maximum sum in subarray spanning a[left..right].

* does not attempt to maintain actual best sequence.

*/int maxsumrec( const vector& a, int left, int right )

int maxrightbordersum = 0, rightbordersum = 0;

for( int j = center + 1; j <= right; j++ )

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

}/**

* driver for divide-and-conquer maximum contiguous

* subsequence sum algorithm.

*/int maxsubsum3( const vector& a )

最大子串行和問題

問題描述 給定乙個整數序列 可能有負數 求一子串行 記為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 最大...

最大子串行和問題

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