歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 用C語言求最大子序列

用C語言求最大子序列

日期:2017/3/1 10:05:52   编辑:Linux編程

給定一整數序列A1, A2,... An (可能有負數),求A1~An的一個子序列Ai~Aj,使得Ai到Aj的和最大

例如:

整數序列-2, 11, -4, 13, -5, 2, -5, -3, 12, -9的最大子序列的和為21。

對於這個問題,最簡單也是最容易想到的那就是窮舉所有子序列的方法。利用三重循環,依次求出所有子序列的和然後取最大的那個。當然算法復雜度會達到O(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)

{

int i,j,v,max=a[0];

for(i=0;i< FONT>

{

v=0;

for(j=i;j< FONT>

{

v=v+a[j];//Sum(i, j+1) = Sum(i, j) + A[j+1]

if(v>max)

max=v;

}

}

return max;

}

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

int max_sub2(int a[], int size)

{

int i,max=0,temp_sum=0;

for(i=0;i< FONT>

{

temp_sum+=a[i];

if(temp_sum>max)

max=temp_sum;

else if(temp_sum<0)

temp_sum=0;

}

return max;

}

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

Copyright © Linux教程網 All Rights Reserved