分治法的核心思想是將 原問題拆解為 若干個規模較小的子問題,而子問題 可以很容易解決,並且最後可以通過子問題的解進行合併來得到原問題的解
分治法是按照分治模式建立的演算法:
分治模式在每層遞迴時都有三個步驟:
一般來講,解決子問題比較簡單,因為子問題已經縮小到了一定規模,很容易求出來;一般通過遞迴呼叫來求解子問題的解,
所以,分治法的核心在於如何 如何拆分子問題 與 合併子問題
**模式如下:
divide-and-conquer(p)
1. if(遞迴終止條件為真)
then return()
2. 將p分解為較小的子問題 p1 ,p2,並進行求解(以 二分為例)
divide-and-conquer(p1) △ 遞迴解決p1
divide-and-conquer(p2) △ 遞迴解決p2
3. 合併子問題的解 來得到原問題的解
首先,思考如何拆分子問題 和 合併子問題
我們將 陣列 從中間拆成兩半,然後分別求出這兩半的 連續最大和,(即子問題的解);然後進行合併,
合併時並不是簡單的比較 子問題的解,因為連續最大和可能由中間的連續子串產生,但是已經被我們拆開,所以要算出中間最大的連續和,然後與子問題的解進行比較,返回其中最大值
class solution
return div_con(nums,0, nums.size()-1);
}private:
int div_con(vector& nums, int left, int right)
//分解為子問題
int mid = left + (right - left)/2;
int leftmax = div_con(nums,left,mid);
int rightmax = div_con(nums,mid+1,right);
//z之後就是通過 子問題的解來求解原問題的解,因為求連續子陣列的最大和,
//所以要不然就是在 左半部分的陣列中,要不然就是在右半部分的陣列中,要不然就是在中間,現在我們
//已經有了左右半部分的最大,所以就是求出中間的最大連續子陣列之和比較即可;這其中要明白過來的一
//點是,我們合併子問題的解也是一步一步來的,要以引數化的一步一步合併,而不是總的一次合併
//從mid中間開始求,進行合併
//注意:合併的時候要以引數化的 left和 right進行處理,因為是對每乙個子問題進行合併;而不能直接
//使用 i>=0 與 j<= nums.size();因為他們代表的是 分解一次的左右部分求合併,但是這裡應該對每一
//子問題求合併,
如題目所示,對陣列進行公升序排序,這裡我們採用 以分治法為核心的歸併排序進行處理
首先,分解原問題,將原問題一分為2,直到子問題很容易排序(即容易得出子問題的解),然後對子問題的解進行合併,得到最後的解
對於 [5,2,3,1]
過程為分解為 [5,2] 和 [3,1]不能輕易得出子問題的解,繼續拆分
[5,2]分解為 [5] ,[2];得出子問題的解,進行合併得到子問題[5,2]的解[2,5]
[3,1]分解為 [3], [1];得出子問題的解,進行合併得到子問題的[3,1]的解[1,3]
所以對 [2,5],[1,3]進行合併,得到原問題的解[1,2,3,5]
在本題中,拆分和求子問題的解均比較簡單,較難的是如何進行合併
class solution
private:
void mergesort(vector& nums,vector& tmp,int left, int right)
//拆分為子問題
int mid = left + (right - left)/2;
mergesort(nums,tmp,left,mid);
mergesort(nums,tmp,mid+1,right);
//合併子問題
merge(nums,tmp,left,mid,right);
}void merge(vector& nums,vector& tmp,int left,int mid, int right)
else
}while(i <= mid)
while(j <= right)
//將子問題的合併結果拷貝到原陣列中
//這裡出現了乙個錯誤debug花了好長時間,我寫為了 nums[tmpleft] = tmp[tmpleft++]
while(tmpleft <= right)}};
//這裡出現了乙個錯誤debug花了好長時間,我寫為了 nums[tmpleft] = tmp[tmpleft++];
出現這樣錯誤的原因在於c++基礎不牢靠,這樣寫看似沒什麼問題,但要注意, = 號運算子是 從由往左運算的,所以這句話相當於
nums[tmpleft+1] = nums[tmpleft];這樣寫會造成溢位錯誤,而且與我們所想表達的內容不符
分治法之快速排序演算法解題思路
快速排序演算法的基本思想是 先找乙個基準元素 比如待排序陣列的第乙個元素 進行一趟快速排序,使得該基準元素左邊的所有資料都它小,而右邊的所有資料都它大,然後再按此方法,對左右兩邊的資料分別進行快速排序,整個排序過程可以 遞迴進行,以此達到整個陣列變成有序序列。比如我們現在對序列arr 這6個數進行排...
分治法排序
分治法排序 1 把大問題分為小問題 2 求每個小問題的解 3 和1反方向,把各個解合併起來 實現 1 啟用兩個快取,乙個放前半部份問題,乙個放後半部份問題 2 只用乙個大快取,用index的大小區分問題規模 include include void megre pre int pre,int fir...
分治法排序
include include define temp 10 int a temp int b temp void merge int low,int mid,int high else k while i mid while j high for i 0 i k i b low i a i int...