問題
給定整數: ,
求 的最大值(為方便起見,如果所有的整數均為負數,則最大子串行和為0)
例如對於輸入:-2,11,-4,13,-5,-2,答案為20,即從到
分析這個問題之所以有意思,是因為存在很多求解它的演算法。
解法一:窮舉遍歷
老老實實的窮舉出所有的可能,**如下:
//計算並返回所最大子串行的和:窮舉遍歷
int maxsubsum1(const vector& a)
//儲存兩者的最大值
if(thissum > maxsum)
maxsum = thissum;
} }return maxsum;
}
這是大多數人都會想到的方法:把所有的可能都列舉出來,然後再把子序列的所有值都加起來求和。
簡單粗暴的解決了問題,而且還很好理解。
//計算並返回所最大子串行的和:窮舉優化
int maxsubsum2(const vector& a)
} return maxsum;
}
解法三:分而治之
分而治之,顧名思義分為兩個部分
分:把大問題分成大致相等的兩個子問題,然後遞迴的進行求解。
治:把兩個子問題的解合併到一起並再做少量的附加工作。
在最大子串行和的問題裡,最大子串行的和可能出現在三個地方:
整個出現在輸入資料的左半部
整個輸入資料的右半部
橫跨左右兩個部分
對於前兩種可以遞迴求解,對於第三種,可以把左右兩個部分的和分別求出,然後加在一起。
具體的**如下:
//計算並返回所最大子串行的和:分而治之
int maxsubsum3(const vector& a,int left,int right)
//獲取中點
int center = (left + right) / 2;
/* 整個出現在輸入資料的左半部的最大子串行求和 */
int leftmaxsum = maxsubsum3(a,left,center);
/* 整個出現在輸入資料的右半部的最大子串行求和 */
int rightmaxsum = maxsubsum3(a,center+1,right);
//計算左右兩個子串行求和結果的最大值
int lrmaxsum = max(leftmaxsum,rightmaxsum);
/* 橫跨左右兩個部分的最大子串行求和 */
//從center向左處理左半邊
int maxleftsum = 0;
int leftsum = 0;
for (int i = center; i >= left; i--)
//從center向右處理右半邊
int maxrightsum = 0;
int rightsum = 0;
for (int j = center+1; j <= right; j++)
//返回求和和前面算出結果的最大值
return max( lrmaxsum, maxleftsum+maxrightsum);
}
解法四:聯機演算法
先來解釋一下聯機演算法的概念:
聯機演算法:在任意時刻,演算法對要操作的資料唯讀入(掃瞄)一次,一旦被讀入並處理,它就不需要在被記憶了。而在此處理過程中演算法能對它已經讀入的資料立即給出相應子串行問題的正確答案。具有這種特性的演算法叫做聯機演算法(on-line algorithm)。
對於這個問題,**如下:
//計算並返回所最大子串行的和:最優演算法
int maxsubsum4(const vector& a)
return maxsum;
}
另附聯機演算法+記錄路徑的題: C語言演算法最大子列和問題三種解法
方法一 雙指標 i,j滿足 i每次對 i,j 區間求和找出最大的值,複雜度是 o n 2 include include define n 1000000 int main for i 0 i n i printf d d d n sum,a tempi a tempj 方法二 分治法,分為左中右三...
最大子段和 三種方法
今天參加了一場洛谷網的比賽,深受打擊.寒假過了這麼多天,一直沒有認真學習演算法,以至於現在的水平比兩個月前還要低.本來就沒有多少底子,又退步了許多,感慨萬分.在洛谷上看到這麼一道題 最大子段和 如果資料小的話,用暴力列舉很簡單就可以做出來了,時間按複雜度位o n 3 可是一道演算法題怎麼會這麼簡單呢...
演算法導論 最大子陣列問題的三種解法
演算法導論 最大子陣列問題的三種解法 標籤 空格分隔 演算法導論 首先補充兩個數學公式 a lo gbc clog baa c alogb c cl ogb alo g n nlog n log n theta nlogn log n nlog n 什麼是最大子陣列問題?給定一陣列a,尋找a中和最大...