轉載請聲明出處:http://blog.csdn.net/zhongkelee/article/details/45485943
一、分治法的基本思想
分治法的適用條件
分治法所能解決的問題一般具有以下幾個特徵:
(1)該問題的規模縮小到一定程度就可以容易地解決。
(2)該問題可以分解爲若干個規模較小的相同問題,即該問題具有最優子結構性質。
(3)利用該問題分解出的子問題的解可以合併爲該問題的解。
(4)該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子問題。(對於有公共部分的子問題,用動態規劃較好,後續博客會講解)
分治法的基本步驟
devide-and-conquer(P)
{
if (|P| <= n0) adhoc(P);//解決小規模問題
devide P into smaller sub-instances P1,P2,...,Pk;//分解問題
for (i = 1; i <= k; i++)
yi = devide-and-conquer(Pi);//遞歸地解各個子問題
return merge(y1,y2,...,yk);//將各個子問題的解合併爲原問題的解
}
人們從大量實踐中發現,在用分治法設計算法時,最好使子問題的規模大致相同,即將一個問題分成大小相等的k個子問題的處理方法是行之有效的。這種使子問題規模大致相等的做法是出自一種平衡子問題的思想,它幾乎總是比子問題規模不等的做法要好。
分治法的複雜性分析
分治法將規模爲n的問題分成k個規模爲n/m的子問題去解。設分解閥值n0=1,且adhoc解規模爲1的問題耗費1個單位時間;再設將原問題divide爲k個子問題和用merge將k個子問題的解合併爲原問題的解需用f(n)個單位時間。用T(n)表示該分治法解規模爲|P|=n的問題所需的計算時間,則有
應用主定理求得方程的解。
下面討論一些運用分治策略的實例。
二、二分搜索技術
給定已按升序排好序的n個元素a[0:n-1],現要在這n個元素中找出以特定元素x。
分析:
1.該問題的規模縮小到一定的程度就可以容易地解決;
2.該問題可以分解爲若干個規模較小的相同問題;
3.分解出的子問題的解可以合併爲原問題的解;
4.分解出的各個子問題是相互獨立的。
無論是在前面還是後面查找x,其方法都和在a中查找x一樣,只不過是查找的規模縮小了。這就說明了此問題滿足分治法的第二個和第三個適用條件。很顯然此問題分解出的子問題相互獨立,即在a[i]的前面或後面查找x是獨立的子問題,因此滿足分治法的第四個適用條件。
二分搜索算法實現:
#include <iostream>
using namespace std;
int BinarySearch(int arr[], int x, int left, int right){
while(left <= right){
int middle = (left + right)/2;
if (arr[middle] == x)
return middle;
if (arr[middle] > x)
right = middle - 1;
else
left = middle + 1;
}
return -1;
}
int main()
{
int array[] = {0,1,2,3,4,5,6,7,8,9};
cout << "0 in array position: " << BinarySearch(array,0,0,9) << endl;
cout << "9 in array position: " << BinarySearch(array,9,0,9) << endl;
cout << "2 in array position: " << BinarySearch(array,2,0,9) << endl;
cout << "6 in array position: " << BinarySearch(array,6,0,9) << endl;
cout << "10 in array position: " << BinarySearch(array,10,0,9) << endl;
return 0;
}
運行結果:
算法複雜度分析:
每執行一次算法的while循環,待搜索數組的大小減小一半。因此,在最壞情況下,while循環被執行了O(logn)次。循環體內運算需要O(1)時間,因此整個算法在最壞情況下的計算時間複雜性爲O(logn)。