据不可靠分析,分治法深得大神们的垂爱,故,想凑近一点认识这个传说中的大法。按照惯例,先上点玄乎的理论晕死一片再说。
基本思想:
- 分解:将问题分解成若干个子问题。
- 治理:递归地解决各子问题。不过若子问题的规模足够小,就以直接的方式(不再递归)解决子问题。
- 合并:将子问题的解合并成原问题的一个解。
- 借用一张要火的图,让我们把它看透:
注意点:
- 子问题和原问题的性质完全一样
- 子问题之间彼此独立
- 递归是分治策略的基础
例1 二分检索略,后面会讲
例2二分归并排序略,后面会讲
例3 hanoi塔的递归算法 略
分治算法的一般性描述
Divide-and-Conquer(P)
- if |P|≤c thenreturn S(P)//最小子问题---可以求解的子问题
- divide P into P1 ,P2 ,...,Pk//将P划分为较小的子问题
- for i←1 to k
- yi ←Divide-and-Conquer(Pi)//递归解决Pi
- return MERGE(y1,y2,...,yk) //合并子问题
注意点:
- 原问题划分成规模较小的子问题,划分要让子问题和原问题的性质完全一样,子问题之间彼此独立规模尽可能均衡。
- 子问题足够小时可求解
- 子问题解的合并是原问题的解
时间复杂度的分析:
显然,时间复杂度有一个的递推方程:
W(n)= W(|P1|)+W(|P2|)+…+W(|Pk|)+f(n),W(c)=C
|P1|,|P2| ,...,|Pk|分别是划分成k个子问题的规模,f(n)为在n规模下合并k个子问题的解的工作量,W(c)=C,表示规模是c(n=c)的子问题工作量是C
两类常见的递推方程的渐进解:
Hanoi塔:W(n)=2 W(n-1)+1,属于(1)类;二分检索:W(n)=2W(n/2)+1,属于(2)类;二分归并排序:W(n)=2 W(n/2)+n-1,属于(2)类
递推方程(1)求解法有:迭代法,递归树法;递推方程(2)求解法有:迭代法,递归树法,换元法,主定理
递推方程(2)在一些条件下的渐进解
下面讲一个具体的例子,可以参照着上面的定义,争取意会意会分治的精髓,*_*
例1 快速排序
该方法的基本思想是:
- 先从数列中取出一个数作为基准数。
- 划分过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。这一步的划分实现可以有多种实现。
- 再对左右区间重复第二步,直到各区间只有一个数。
划分实现一:
说明:以第一个元素为基准数,分别从数组的前面和后面开始找,前面借用指针i找比基准数大的数,后面借用指针j找比基准数小的数,然后找到的数交换。
划分实现二:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
i |
|
|
|
|
|
|
|
| j |
以第一个元素为基准,令X=72,i=0,j=9
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
i |
|
|
|
|
|
|
| j |
|
把j位置的元素赋值给i位置,从左往右找大于或等于X的元素位置,用i记录
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
|
|
| i |
|
|
|
| j |
|
把i位置的元素赋值给j位置,从右往左找小于或等于X的元素位置,用j记录
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 88 | 85 |
|
|
| i |
| j |
|
|
|
|
依次重复以上数据,直到i==j,把X赋值给该位置
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
48 | 6 | 57 | 42 | 60 | X=72 | 83 | 73 | 88 | 85 |
|
|
|
|
| i ==j |
|
|
|
|
说明:略。
时间复杂度(以第一个为基准元素):
最坏情况: 每次划分一个划了0规模,一个划了n-1的规模,相当于数组本来有序,但是倒序。W(n)=W(n-1)+n-1,W(1)=0,从而有W(n)=n(n-1)/2=O(n^2)
最好划分:W(n)=2W(n/2)+n-1,W(1)=0,从而有W(n)=Θ(nlgn)
均衡划分的时间复杂度:每次划分保持子问题的规模比例,例如:1:9,如下:T(n)=T(n/10)+ T(9n/10)+n, T(1)=0, 从而有T(n)=Θ(nlgn),我们用递归树求解其渐进解。
该递归树左边最先到达规模为1的子问题,右边缓之。取一个渐进上界,进而计算树的层数,而n (9/10)^k=1,得出k的取值是k=clgn,故T(n)=kn=kc*nlgn,故T(n)=O(nlgn)。
平均时间复杂度:略。
转载请注明出处。
参考:
https://www.bilibili.com/video/av7134874/?from=search&seid=14261249226249986779