经典算法之分治法 递归与分治 学习笔记
分治法思想
当要求解的问题规模较大时,将一个难以解决的大问题分割成一些规模较小的相同类子问题,以便各个击破,分而治之。
四大特征
该问题的规模缩小到一定的程度就可以容易地解决;
该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
利用该问题分解出的子问题的解可以合并为该问题的解;
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
应用条件
1.大问题可以分割成k个子问题(1<k<=n );
子问题规模仍不够小,则可以继续递归划分
2.子问题均可解;
通常是原问题的较小模式,通常可以采用递归求解
3.子问题的解可以求出原问题的解;
将解合并成原问题的解,自底向上
复杂性分析
T ( n ) = { O ( 1 ) n = 1 k T ( n / m ) + f ( n ) n > 1 T\left( n \right) =\left\{ \begin{array}{c} O\left( 1 \right) \ \ \ \ \ \ \ \ \ \ \ \ \ n=1\\ kT\left( n/m \right) +f\left( n \right) \ n>1\\ \end{array} \right. T(n)={O(1) n=1kT(n/m)+f(n) n>1
其中,f(n)代表n/m个子问题合并成原问题的解需要的时间;k为分解成的子问题的个数;n/m为子问题的规模。
根据迭代法,求解得到:
T
(
n
)
=
n
log
m
k
+
∑
j
=
0
log
m
n
−
1
k
j
f
(
n
/
m
j
)
T\left( n \right) =n^{\log _mk}+\sum_{j=0}^{\log _mn-1}{k^jf\left( n/m^j \right)}
T(n)=nlogmk+j=0∑logmn−1kjf(n/mj)
递归函数
当一个函数及它的一个变量是由函数自身定义时,称这个函数是双递归函数。
分治法应用
-
二分搜索问题
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x。
代码如下:
template<class Type>
int BinarySearch(Type a[], const Type& x, int l, int r){
while (r >= l){
int m = (l+r)/2;
if (x == a[m]) return m;
if (x < a[m]) r = m-1;
else l = m+1;}
return -1;
}
最坏情况下的计算时间复杂性为O(logn)
先留下目录,对应算法慢慢更。