分治策略之最大子陣列
一、基本思想
分治策略是將父問題差分成的多個子問題,然後遞迴的方式解決子問題。整個思想和動態規劃類似,不過分治策略不要求最優解問題,而只是把父問題分解成子問題。步驟:
分解(Divide)
先將問題劃分成子問題。子問題的形式與原問題相同。
解決(Conquer)
遞迴解決問題,當問題縮小到一定程度就能夠直接求解。
合併(Combine)
當最小子問題解決後,遞迴已經觸底迴歸,逐漸將子問題答案合併成父問題解。
二、事例
給一個數組a[0…n],假設a[s…t]是它的子陣列,那麼這個子陣列的所有元素加起來最大是多少?用數學語言形式化的描述就是:求0<=s<=t<=n 使得 a[s]+a[s+1] …. + a[t] 最大。
暴力求解:
暴力破解只需要遍歷陣列就能夠解決:
先假設最大子陣列從a[0]開始,接下來只需要從a[0]開始延伸a[0] a[0]a[1] a[0]a[1]a[2]…..
再假設最大子陣列從a[1]開始,接下來只需要從a[1]開始延伸a[1] a[1]a[2] a[1]a[2]a[3]…..
再假設最大子陣列從a[2]開始,接下來只需要從a[2]開始延伸a[2] a[2]a[3] a[2]a[3]a[4]…..
…….如此便把所有子陣列都考慮了一遍。
分治策略:
Divide:
使用分治策略,我們儘量將父問題分解成規劃相等的子問題。所有找到陣列中間位置mid,將陣列分成兩個部分。即a[low,mid] 和 a[mid,high]。
在考慮下答案,很明顯,最後答案要不在a[low,mid]中,要不就在a[mid,high]中,或者橫跨兩個陣列(這是答案必定包含a[mid])。
Conquer:
我們父問題分解成三個子問題。其中我們發現:
1、求a[low,mid]最大子陣列和和a[mid,high]最大子陣列和其實和父問題是一樣的形式,只不過規模不一樣。因此這兩個子問題我們只需要遞迴就能夠求解。
2、求橫跨兩個陣列(這是答案必定包含a[mid])最大子陣列和問題,這個問題與父問題形式是不同的,但是這個問題有個關鍵因素答案必定包含a[mid],因此我們只需要從a[mid]向兩邊延伸求和就能解出答案。
Combine:
最終答案的合併就是遞迴的迴歸,從最小子問題一直迴歸到父問題。答案就直接解出。
Code:
看函式的返回值:通過if語句找出三個子問題的最大陣列和再返回到父問題。是不是就是相當於把子問題的答案經過比較返回最大陣列和作為父問題的最優解。該問題其實就是動態規劃問題。