!!复习算法考试所用,代码为老师课堂手写,逻辑没错,应该有点小问题,需要修改才能运行,仅供思路参考
递归
递归:自身调用自身
定义:直接或间接的调用自身的算法称为递归算法,用函数自身给定出定义的函数称为递归函数
如线性查找
int find(T *a,int l,int r,const T &x)//其实也就是从0依次往后找,emmm强行递归
{
//在a[l]....a[r] 查找x
if(r<l) return -1;
if(l==r&&a[l]==x)
{
return l;
}
else {
return -1;
}
int m = (l+r)/2;
//区间分为l,...m 和 m+1....r
int r1 = find(a,l,m,x);
if(r1>=0) return r1;
else{
return find(a,m+1,r.x);
}
}
同时求最值
template<class T>
T getMax(T *a,int l,int r)
{//求a[l].....a[r]的最大值
if(l==r)
return a[l];
int m = ( l + r ) / 2;
//注:当r>l时,m>=l,m<r
T m1 = getMax(a,l,m);
T m2 = getMax(a,m+1,r);
return m1>m2?m1:m2;
}
分析:
T(n) = 0 n=1
T(n) = 2T(n/2)+1 = 2^k* T(1) + 2^(k-1) + 2^(k-2)...+1 = n-1 (k = log2(n)) n>1
同时求最大最小值
注:stl中有pair
相当于
template<class T1,class T2>
struct pair
{
T1 first;
T2 second;
}
分治求最大及最小
template<class T>
pair<T,T> minMax(T *a,int l,int r)
{
//即求a[l]...a[r]的最大值及最小值
pair<T,T> v;
if(l==r)
{
v.first = a[l];
v.second = a[l];
return v;
}
//下面是 l<r
int m = (r+l)/2;
pair<T,T> v1 = minMax(a,l,m);
pair<T,T> v2 = minMax(a,m+1,r);
v.first = v1.first<v2.first?v1.first:v2.first;
v.second = v1.second<v2.second?v2.second:v1.second;
return v;
}
分析:
T(n) = o n<=1;
T(n) = aT(n/2)+2 n>1
递归贼多
总工作量 T(n) = 2+ 2* 2 + 2^2* 2 +.....2^k* T(1)
fibonacci 数列
Fn = 1 n = 0,1
Fn = Fn-2+Fn-1 n>1
不能直接采用递归方法,否则会有大量重复运算
ex:求树高
template<class T>
struct Node{
T data;
Node<T> *l,*r;
}
//树高为层数
template<class T>
int getH(Node<T> *t)
{
if(t==NULL)//空树高为0
{
return 0;
}
Node<T> *lt = t->l;
Node<T> *rt = t->r;
int lh = getH(lt);
int rh = getH(rt);
int maxH = lh>rh?lh:rh;
return (maxh+1);
}
分治策略
分治策略的基本思想 : 问题->分解->分解....->归并
Divide_and_conquer(P){
if(|p|<=n0) //规模足够小
{
y = 非递归方法求解p
return y;
}
//分解 p 到 p1,p2,p3.....;
for(int i = 1;i<=k;i++)
{
yi = Divide_and_conquer(pi);
}
y = Merge(y1....yk);
return y;
}
分析(递归方程)
T(n) = C(常量) n<=n0
T(n) = k* T(n/m) + f(n) n>n0
注 :
- n/m 为子问题的规模
- k 为子问题个数
- f(n) = D(n) + M(n)分别为 分解工作量 和 合并工作量
- f(n) = θ(n^d) 或 f(n) = O(n^d) 即分解+合并工作量为多项式级别
如:同时求最大最小问题中
T(n) = 2 * T(n/2)+( 0 + 2 ) 分别为分解(仅作(l+r)/2,无比较),比较(两次元素比较)
归并排序
a[0].......a[n-1]
计算中间下标:m = (l+r )/2 无比较,即D(n) = 0
归并 合并工作量
- Mmax(n) = n - 1
- Mmin(n) = n/2
归并排序
Tmin(n) = 0 n<=1
Tmin(n) = 2 * Tmin(n/2) + n/2 n>1
Tmax(n) = 0 n<=1
Tmax(n) = 2 * Tmax(n/2) + n-1 n>1
或者
- T(n) = 0 n<=1
- T(n) = 2* T(n/2) + O(n) n>1
快速排序
- 最坏 : T(n) = n*(n-1)/2
- 最好 : T(n) = 2 * T(n/2) + (n-1) = θ(nlogn)
密码学中
如计算 x^64 mod 65537, x^1024 mod 65537,
且注意到 x^2048 = x^1024* x^1024
- T(n) = 0 n =1
- T(n) = 2* T(n/2)+1 n为偶数
- T(n) = T(n-1)+1 n为奇数
x^n = x^(n/2)* x^(n/2) n为偶数
x^n = x^(n-1)* x n为奇数
最有效 非递归模重复平方算法
主定理
设T(n)= C n =1
设T(n)= k*T(n/m) + θ(nd)(θ(nd) = D(n)+M(n) 或 O(n^d) 为多项式级别)
k>=1 , m>=1
存在
- T(n) = θ(n^d) d>logm(k)
- T(n) = θ(n^d*logn) d=logm(k)
- T(n) = θ(n^(logm(k))) d<logm(k)
如T(n) = 2T(n/2) + θ(n)
此处 k = 2 ,m = 2 , d =1 =>d=logm(k) =>T(n) = θ(n^d* logn) = θ(n* logn)
二分查找(最坏情况)
T(n) = T(n/2)+1
此处 k =1, m = 2 , d =0 =>d = logm(k) => T(n) = θ(logn)
同时求最大最小
T(n) = 2* (T/2) + 2;
=>k = 2,m = 2,d = 0 d<log2(2) =>θ(n)
求解递归方程
方法一: 直接展开
对于 f(n) = θ(n^d)
T(n) = n^d + (k/(m^d))* n^d +......(k/(md))(l-1)* n^d.....
注:1+r+r2+.....rl
- r<1 上式极限为常数
- r=1 上式为l
- r>1 相当于 r^(l+1)
方法二:运用主定理
当 k = m^d 即 d = logm(k)
=>T(n) = l* n^d + O(n^(logm(k))) = (logm(n))* n^d + θ(n^d) =(logm(n)+1)* n^d = θ(logn* n^d)
当 k < m^d 即 d > logm(k)
=>T(n) = θ(n^d)
当 k > m^d 即 d < logm(k)
=>T(n) = θ(n^logm(k))