一、递归与分治概述:
1、分治方法在于分和治。将一定规模的问题划分成性质相同的若干个小问题,分;对于每个小问题,进行所需要进行的操作,如排序等。
2、关于递归:
(1)递归中需要的成分是递归边界和递归规则,没有递归边界递归无法停止、无法进行。
(2)通过将各层的关系从小到大逐渐带入,可以求解出一个函数的非递归表达式。
(3)n该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
3、Ackerman函数:
Ackerman函数的定义为:
根据关系可以递推出来:
在m取不同的值的过程中,该函数的递推关系式也不同。只是一种无法用单一的非递归关系表达的函数。
4、在Ackerman函数中,定义它的逆拟函数α(n)为使A(x)>n成立的最小的x。
5、整数划分问题:
对于整数的不同划分,考虑以下几种不同的情况:(1)m>n:q(n,m)=q(n,n)
(2)m=n:q(n,m)=1+q(n,m-1)
(3)m<n:q(n,m)=w(n,m)+q(n,m-1)
又:w(n,m)=q(n-m,m)
(4)m=1:q(n,1)=1
6、汉诺塔问题:
思路:将前n-1个元素移动到c上,然后将第n个移动到b上,再将c上的n-1个移动到b上。
注意边界条件是:如果只有一个元素,直接move到b上。
void Move(int no,char a,char b){
printf("Move %d from %c to %c.\n",no,a,b);
}
void Hanoi(int n,char a,char b,char c){
if(n==1){
Move(1,a,b);
}
else{
Hanoi(n-1,a,c,b);
Move(n,a,b);
Hanoi(n-1,c,b,a);
}
}
7、分治法的基本思想:将一个叫难解决的大问题分成k个规模较小的子问题,逐个解决,分而治之。如果问题的规模还不够小,就继续划分,直到可以直接解决这个小问题。将求出的小问题自下而上的合并,最终得到问题的解
8、递归的概念:
递归算法:直接或间接地调用自身的算法。
递归函数:用函数自身给出定义的函数。
使用递归技术使得算法的描述简捷且易于理解
10、分治法满足的要求:
(1)问题的规模缩小到一定的程度就可以解决
(2)该问题可以分成若干个规模较小的子问题
(3)该问题分解出的子问题的解可以合并成为问题的解
(4)问题没有重叠的子问题
11、分治法的基本步骤:
divide-and-conquer(P)
{
if ( | P | <= n0) adhoc(P); //解决小规模的问题, adhoc(P)是基本子算法
divide P into smaller subinstances P1,P2,...,Pk;//分解问题
for (i=1,i<=k,i++)
yi=divide-and-conquer(Pi); //递归的解各子问题
return merge(y1,...,yk); //将各子问题的解合并为原问题的解
}
二、二分搜索技术
1、时间复杂性是O(logn) 。
2、核心代码:
int BinarySearch(int a[],int l,int r,int n){
while(l<=r){
mid=(l+r)/2;
if(a[mid]==n){
return mid;
}
else if(a[mid]>n){
r=mid-1;
}
else l=mid+1;
}
return -1;
}
三、大整数的乘法
1、原始方法:XY的花费时间:n²
2、拆分成两块:
X = a 2n/2 + b Y = c 2n/2 + d
XY = ac 2n + (ad+bc) 2n/2 + bd
其中ac等要花费的时间:(n/2)^2=n^2/4,有四个部分:有T(n)=4*T(n/2)+O(n)。
利用公式得到:
T(n)=O(n^2)
3、在拆成两块的情况下:XY=ac2^n+((a-b)(d-c)+ac+bd)+bd
则只有三个要计算的小部分:
利用公式得到的:T(n)=3T(n/2)+O(n)=O(n^1.59)
4、入果将整数拆分成更小的小块,就可以更好运行的效率
四、stressen矩阵乘法:
1、每计算一个c[i][j],就需要计算O(n^3),(即使矩阵的长和宽不是都等于n,但肯定可以表示成n的几分之几)
2、改进:将矩阵分割成均匀的四个,则有:
还是O(n^3)
3、构建几个辅助作用的矩阵:
得到的是
则有:
O(n^2.81)
五、最接近点对问题:
在一个平面中,想要去求两个最接近的点:基本的方法是蛮力O(n^2)
(一)一维情况下:
1、原始方法:(1)对一维的坐标进行排序O(nlongn)
(2)依次计算相邻两个点的距离O(n)
所以T(n)=O(nlongn)
2、想设计出一种用分治的、可以推广到二维的算法:
(1)将各个点分到s1、s2中去(O(n))
(2)分别查找s1,s2中的最短的距离(2T(n/2))
(3)(在线性时间内)找到s1,s2中最大和最小的点,计算二者的距离,与得到的s1,s2,中的最短的距离比较,选出来最小的(O(n))
注意此处:s1,s2中最大和最小的点肯定在中间位置的左边-d,与右边+D中,因为要不就里面没点;要不里面有点但是只是左边右边空间里面各有一个,可能导致这两点之间的距离才是整体里最小的,或者不。(如果这两个其中一边或两边中有一个以上的点,就与之前的结论相矛盾
;并且其中没有排序的过程)
可以得到时间复杂度:
T(n)=O(nlogn)
(二)二维情况下
T(n)=O(nlogn)
六、棋盘覆盖问题
七、合并排序
1、流程
void MergeSort(Type a[ ], int left, int right)
{
if (left<right) {//至少有2个元素
int i=(left+right)/2; //取中点
mergeSort(a, left, i);
mergeSort(a, i+1, right);
merge(a, b, left, i, right); //将排好序的集合合并到数组b
copy(a, b, left, right); //复制回数组a
}
}
2、其中,取中点:O(1)
左边合并T(n/2),右边合并T(n/2)
合并O(n),复制回原来的数组O(n)
,T(n)=O(nlogn)
关于求解有不同的方法:
3、合并排序的新方法:从底向上两两合并/将原来的序列化分成若干个有序段(自然排序),之后进行两两合并
注意:自然排序最好的时间复杂度是O(n),因为原来已经排好了,只需要扫描一遍
.八、快速排序
1、快排的思路:
(1)选择第一个元素为基准
(2)在两头分别设置指针i和j,如果i的元素比基准还要小或者等于就继续向后,同理右边
找到不合适的二着就交换位置。
(3)如果i在j右边了,就让j指向的元素和基准元素交换位置。
2、关于时间复杂度:
(1)最坏情况下(逆序):
T(n)=O(n^2)
(2)平均情况下:
T(nlogn)
3、代码的框架:
template<class Type>
void QuickSort (Type a[ ], int p, int r)
{
if (p<r) {
int q=Partition(a,p,r);
QuickSort (a,p,q-1); //对左半段排序
QuickSort (a,q+1,r); //对右半段排序
}
}
4、算法的改进:可改进之处是,可以在选择基准的时候随机的选择
template<class Type>
void QuickSort (Type a[ ], int p, int r)
{
if (p<r) {
int q=Partition(a,p,r);
QuickSort (a,p,q-1); //对左半段排序
QuickSort (a,q+1,r); //对右半段排序
}
}
九、线性时间选择:
1、我们需要在n个无序的元素里面找出来第k小的元素。
2、基本思路:
selet中:
(1)以第一个元素为基准,进行(选择随机数的)一次的快排,返回拍好后基准元素的位置i
(2)①如果头到i的元素个数是小于等于k的,就在头到i这一段进行递归的select
②如果k大于前面的个数,就在后面这段进行查找select
(3)如果是只有一个元素了,就直接返回这个位置。
template<class Type>
Type RandomizedSelect(Type a[ ], int p, int r, int k)
{
if (p==r) return a[p];
//一次快速排序,随机选择基准元素,划分数组
int i=RandomizedPartition(a,p,r),
j=i-p+1; // j为a[p,i]中元素个数
if (k<=j) return RandomizedSelect(a,p,i,k);
//返回第k-j小元素
else return RandomizedSelect(a,i+1,r,k-j);
}
3、时间复杂度:
=
最坏的情况:我想要找最小的,但总是随机选中一个最大的做划分,此时:
,T(n)=O(n2)
4、改进:如果每次都可以找到一个数字,使得至少划分出来的个数为原来的b倍,则也可以确保时间复杂度为:O(n)
十、选择划分基准
1、
2、注意:(1)其中组别是从0到(p-q+4)=((p-q+1)-5)/5,(数组长度)
(2)在75长度以内的数组可以自行通过排序直接查找,效率有保障。
(3)其中最主要的有三步:
①每组进行排序并将中位数交换位置(c1n)
②在中位数中select选择中位数(T(5/n))
③在选择出的段中进行再一次的select(T(3n/4))
来源:https://blog.csdn.net/qq_41464448/article/details/90178357