分治法的解題總結

2021-09-27 13:16:12 字數 2838 閱讀 2038

分治法的核心思想是將 原問題拆解為 若干個規模較小的子問題,而子問題 可以很容易解決,並且最後可以通過子問題的解進行合併來得到原問題的解

分治法是按照分治模式建立的演算法:

分治模式在每層遞迴時都有三個步驟:

一般來講,解決子問題比較簡單,因為子問題已經縮小到了一定規模,很容易求出來;一般通過遞迴呼叫來求解子問題的解,

所以,分治法的核心在於如何 如何拆分子問題 與 合併子問題

**模式如下:

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...