最大子序列和線性算法

最大子序列和線性算法
 
問題描述:
       給定整數A1, A2,……AN (可能有負數),求I到j的最大值。
例如:
       -2, 11, -4, 13, -5, -2時答案爲20
 
對於這個問題的算法有很多,當然我要說的是使用“動態規劃”算法實現的程序,對於這個算法,我可以說很多人都曾經想到,但是沒有想全(因爲我就是這樣的)。還有一點對於這個問題的動態規劃的解法是非常經典的,她的時間複雜度是O(n),也就是線性的。而對於窮舉法它的時間複雜度可是O(n3), 這樣看來可以巨大的改進了。
 
考慮這樣的一個問題,我們從最簡單的左邊開始看,就如上面的例子,-2對於結果有影響嗎?回答是沒有。那麼讓我們看下面這樣一個例子:
       6, -7, ……
       此時,我們還需要考慮6 和 –7 嗎,有些人說要的,因爲可能對於6,後面沒有比其更大的了,是啊。問題是這樣的。那麼對於後面的結果分析其有影響嗎?這個時候我們可以說沒有影響的!
       到現在,上面是不是大家多曾經想到了呢?呵呵,我曾經就想到了,那我們爲什麼不把這問題,推倒後面呢?動態規劃法就是解決這樣的一個問題,我們知道此時前面的兩個數就是一種最優的子結構(儘管只有2個數,不過是完全可以推廣的。)
       書中的算法就告訴我們是如何推廣的,我寫這樣的一篇文章的具體目的也就是爲了說明以上的問題,因爲我和大家一樣都曾經想到了前面的算法,卻沒有考慮下去。以此感慨!並遺憾!
       那麼書中的算法是這樣的:(看這個算法之前應該先知道這個問題的“分治法”的求解,這樣更讓你覺得,這個算法的完美之處。)

 
Int MaxSubsequenceSum(const int A[], int N)
{
       int ThisSum, MaxSum, j;
       ThisSum = MaxSum = 0;
       For(j=0; j < N; j++)
{
              ThisSum += A[j];
              If (ThisSum > MaxSum)
                     MaxSum = ThisSum;
              Else if(ThisSum < 0)
                     ThisSum = 0;
}
return MaxSum;
}

       對於這個算法的分析(邏輯):
              從左相右相加,若結果不斷的增加,那麼ThisSum將同MaxSum一起增加,如果遇到負數,那麼也加到ThisSum上去,但是此時ThisSum < MaxSum,那麼就不加。看ThisSum是不是會回升,若一直不回升,不斷或是波浪型的下降,那麼當它降到0時,說明前一段與後一段是可以拋棄的。正如有 7 , -8 一樣,我們可以不要這兩個數,但是我們知道MaxSum依然保存着前一段的最大值,(這就是這個算法中的厲害,我認爲)。然後,ThisSum將從後面開始將這個子段進行分析,若有比當前MaxSum大的子段,然後替換(此時可以徹底拋棄前一段)。這樣一趟掃描結果也就出來了。
 
後記:
       對於這個問題,一開始對於分治算法,我們可能很容易想對,而對與動態規劃可能我們很難想到(至少我沒有那麼輕易就想到了)。儘管如此,還是比較慶幸想到了其最優子結構,問題解決到此,當然對於這個問題,我們還是可以用“分治”算法,其時間複雜度爲:O(nlogn),也是比較優的,當然沒有上面提到的優。   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章