關於分治法
分治法,分而治之。就是將原問題划分為n個規模較小,結構與原問題類似的小問題進行處理,遞歸地解決這些問題,然后再合並求解的過程。
分治法在解決的流程上分為三個步驟:
1.分解:將原問題划分為n個規模較小,結構與原問題類似的小問題。
2.解決:若子問題規模小,足以處理,則求解,否則繼續遞歸處理。
3.合並:將子問題的解,合並成為原問題的解。
面試題:矩形覆蓋
我們可以用2*1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用number個2*1的小矩形無重疊地覆蓋一個2*number的大矩形,總共有多少種方法?
分析:我們化繁為簡,從下面的示例說起(設該問題的處理函數為rectCover)。
由於小矩形的尺寸是2×1,所以有大矩形為2×number的存在,那么我們第一步就可以有兩種處理方式:
第一步如果選擇豎方向填充,那么該問題的規模就縮減為對於剩余的2×(number-1)的大矩形的填充。
如果,第一步如果選擇橫方向的填充,則第二排的前面兩個小矩形也只能如此填充,那么該問題的規模就縮減為對於剩余的2×(number-2)的大矩形的填充.
結合上述分析,很容易得到遞推的關系: rectCover(number)=rectCover(number-1)+rectCover(number-2)。當然此處也要注意遞歸跳出條件的判定。
下面是對應的算法
1 class Solution { 2 public: 3 int rectCover(int number) { 4 if(number<=0) return 0; 5 if(number==1) return 1; 6 if(number==2) return 2; 7 else 8 return rectCover(number-1)+rectCover(number-2); 9 } 10 };
當然,遞歸的實現必須借助棧,而且存在很多重復計算的數據。不妨取number=5,遞推的過程如下。可以看出rectCover(3)計算2次,rectCover(2)計算3次,rectCover(1)計算2次。所以遞歸的效率比較低下,下篇 動態規划法面試題(一):矩形覆蓋會繼續探討這個問題,給出另一種“高效”的解法。