第2讲 分治策略
第2章 递归与分治_作业答案讲解
具体执行过程:求最大值
0 1 2 3 4 5 6 7 8 9 10 11 12 13 24 -13 29 113 87 65 -9 36 14 76 44 83 67 5 0 1 2 3 4 5 6 24 -13 29 113 87 65 -9 0 1 2 3 24 -13 29 113 0 1 24 -13 2 3 29 113 4 5 6 87 65 -9 7 8 9 10 11 12 13 36 14 76 44 83 67 5 7 8 9 10 36 14 76 44 7 8 36 14 7 36 9 10 76 44 11 12 13 83 67 5 11 12 83 67 11 83 12 67 13 5
课后练习
• 练习2:分析如下时间函数的复杂度,并说明 原因。 1. 利用递归树说明以下时间函数的复杂度:
O(1) T ( n) 3T ( n ) O( n) 4 n1 n1
2. 利用主定理说明以下时间函数的复杂度:
T(n) = 16T(n/4) + n
T(n) = T(3n/7) + 1
课后练习
• 练习1:给定数组a[0:n-1], 1. 试设计一个分治法算法,找出a[0:n-1]中元素最 大值和最小值; 2. 写出该算法时间函数T(n)的递推关系式; 3. 分析该算法的时间复杂度和空间复杂度。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 24 -13 29 113 87 65 -9 36 14 76 44 83 67 5
• 递归公式:
– 设n个元素的集合可以划分为F(n,m)个不同的由 m个非空子集组成的集合。 F(n,m) = 1, when n=0, n=m, n=1, or m=1 F(n,m) = 0, when n<m 否则 F(n,m)=F(n-1,m-1)+m*F(n-1,m)
分治算法及其典型应用
分治算法及其典型应用
分治算法是一种重要的算法设计策略,它将一个大问题分解成若干个规模较小的子问题,然后递归地解决这些子问题,最后将它们的解合并起来,得到原问题的解。
分治算法在计算机科学和算法设计中有着广泛的应用,可以解决许多实际问题,下面将介绍一些典型的应用。
1. 排序算法。
分治算法在排序算法中有着重要的应用。
其中最著名的就是归并排序和快速排序。
在归并排序中,算法将数组分成两个子数组,分别进行排序,然后合并这两个有序的子数组。
而在快速排序中,算法选择一个基准值,将数组分成两个子数组,分别小于和大于基准值,然后递归地对这两个子数组进行排序。
2. 搜索算法。
分治算法也可以用于搜索问题,例如二分搜索算法。
在这种算法中,将搜索区间分成两个子区间,然后递归地在其中一个子区间中进行搜索,直到找到目标元素或者子区间为空。
3. 求解最大子数组问题。
最大子数组问题是一个经典的动态规划问题,也可以用分治算法来解决。
算法将数组分成两个子数组,分别求解左右子数组的最大子数组,然后再考虑跨越中点的最大子数组,最后将这三种情况的最大值作为整个数组的最大子数组。
4. 矩阵乘法。
分治算法也可以用于矩阵乘法。
在矩阵乘法中,算法将两个矩阵分成四个子矩阵,然后递归地进行矩阵乘法,最后将四个子矩阵的结果合并成一个矩阵。
总的来说,分治算法是一种非常重要的算法设计策略,它在许多实际问题中有着广泛的应用。
通过将一个大问题分解成若干个规模较小的子问题,然后递归地解决这些子问题,最后将它们的解合并起来,我们可以高效地解决许多复杂的问题。
分治法-PPT精选
不成功检索在i级外部结点终止的元素比较次数是i-1
2019/11/26
BINSRCH计算复杂度的理论分析
1)不成功检索的最好、最坏和平均情况的计算时
间均为Θ(logn) ——外结点处在最末的两级上; 2)最好情况下的成功检索的计算时间为 Θ(1)
2019/11/26
以比较为基础的有序检索问题最坏情况的时间下界
定理2.3 设A(1:n)含有 n(n≥1)个不同的元素,排序为A(1)< A(2) < …< A(n)。又设用以比较为基础的算法去判断是 否 xA(:1n) ,则这样的任何算法在最坏情况下所需的最小 比较次数FIND(n)有:
2019/11/26
FIND k(lo ng )1()n
任何一种以比较为基础的算法,在最坏情况 下的计算时间都不低于Ο (logn)。因此, 不可能存在最坏情况比二分检索数量级还低 的算法。
最坏情况下的成功检索的计算时间为 Θ(logn)
2019/11/26
3)平均情况下的成功检索的计算时间分析
利用外部结点和内部结点到根距离和之间的关系进行推导: 记,
由根到所有内结点的距离之和称为内部路径长度,记为I; 由根到所有外部结点的距离之和称为外部路径长度,记为E。
则有,E=I+2n
解。
2019/11/26
DANDC的计算时间
若所分成的两个子问题的输入规模大致相等,则DANDC 总的计算时间可用递归关系式表示,如下:
g(n)
n足够小
T(n) =
2T(n/2) + f(n) 否则
注: T(n):表示输入规模为n的DANDC计算时间 g(n):表示对足够小的输入规模直接求解的计算时间 f(n):表示COMBINE对两个子区间的子结果进行合并
NOIP基础算法讲解2
while(i<=mid)do begin temp[p]:=a[i];inc(p);inc(i);end while(j<=right)do begin temp[p]:=a[j];inc(p);inc(i);end for i:=left to right do a[i]:=temp[i]; end;
数据范围:n≤10^6。所有数之和不超过10^9。
例题8:快速幂
【问题】计算an mod k的值 ,其中n<=109。
方法1:朴素算法。每次乘以a,时间复杂度O(n)。 function power(a,n:longint):longint; var x:longint; begin x:=1; for i:=1 to n do x:=x*a; power:=x; end;
时间效率不尽如人意….. 问题出现在哪里呢??
方法2:分治策略
采用分治求解: ➢划分问题:把序列分成元素个数尽量相等的两半; ➢递归求解:统计i和j均在左边或者均在右边的逆序对个数; ➢合并问题:统计i在左边,但j在右边的逆序对个数。
记数列a[st]~a[ed]的逆序对数目为d(st,ed); mid=(st+ed)/2,则有:
三、分治的三步骤
①划分问题:将要解决的问题分解成若干个规模较 小的同类子问题;
②递归求解:当子问题划分得足够小时,求解出子 问题的解。
③合并问题:将子问题的解逐层合并成原问题的解。
四、分治的框架结构
procedure Divide() begin
分治法
顾铁成
1
引例:称硬币
如果给你一个装有16枚硬币的袋子,其中有一
枚是假的,并且其重与真硬币不同。你能不能 用最少的比较次数,找出这个假币?
为了帮助你完成这个任务,将提供一台可用来 比较两组硬币重量的仪器,利用这台仪器,可
以知道两组硬币的重量是否相同。
2
引例:称硬币
常规的解决方法是先将这些硬币分成两
15
当 k = 1 时,各种可能的残缺棋盘
16
三格板的四个不同方向
17
【输入】
第一行输入棋盘 的总行数,第二 行输入残缺棋盘 的格子坐标。
【样例输入】 4
4 1
【样例输出】 2 2 3 3 2 1 1 3 4 4 1 5
【输出】
覆盖的矩阵图。
0 4 5 5
18
问题分析
很明显,当K=0时,是不需要三格板的,而当
24
【样例输入】 5 3 23 8 91 56 4 【样例输出】 1
25
问题分析
对于一组混乱无序的数来说,要找到第k
小的元素,通常要经过两个步骤才能实 现:
第一步:将所有的数进行排序; 第二步:确定第k个位置上的数。
26
问题分析
传统的排序算法(插入排序、选择排序
、冒泡排序等)大家都已经很熟悉了, 但已学过的排序方法无论从速度上பைடு நூலகம்还 是从稳定性方面,都不是最佳的。
将7作为一个参照数;
将这个数组中比7大的数放在7的左边; 比7大的数放在7的右边;
这样,我们就可以得到第一次数组的调整:
[ 4 2 6 6 1 ] 7 [ 10 22 9 8 ]
29
信息工程系课程的介绍XXXX专业宣讲会
文库贡献者物理与电子信息工程学院信息工程系课程介绍2013年11月目录1. 《算法设计与分析》课程介绍 (1)2. 《离散数学》课程介绍 (2)3. 《计算机组成原理》课程介绍 (3)4. 《网络应用终端开发》课程介绍 (4)5. 《数据结构》课程介绍 (5)6. 《面向对象程序设计(Java)》课程介绍 (6)7. 《嵌入式操作系统基础》课程介绍 (8)8. 《数据结构》课程介绍 (9)9. 《操作系统A》课程介绍 (11)10. 《多媒体技术A》课程介绍 (12)11. 《ARM原理与应用》课程介绍 (13)12. 《ERP系统实施及二次开发技术》课程介绍 (14)13. 《Internet开发基础(JSP)》课程介绍 (15)14. 《IP统一通信技术》课程介绍 (17)15. 《IT项目管理》课程介绍 (18)16. 《嵌入式系统软件开发》课程介绍 (19)17. 《面向对象程序设计A》课程介绍 (20)18. 《Web应用开发》课程介绍 (22)19. 《Xml与Web Service》课程介绍 (24)20. 《编译原理》课程介绍 (26)21. 《数据库原理与应用》课程介绍 (27)22. 《电子商务概论》课程介绍 (28)23. 《企业运作模拟》课程介绍 (29)24. 《信息系统分析与设计》课程介绍 (31)25. 《管理学原理》课程介绍 (32)26. 《会计学原理》课程介绍 (34)27. 《数字电路与逻辑设计》课程介绍 (35)28. 《程序设计基础》课程介绍 (36)29. 《计算机网络》课程介绍 (38)30. 《计算机网络安全》课程介绍 (39)31. 《计算机网络规划与设计》课程介绍 (40)32. 《路由与交换技术》课程介绍 (41)33. 《企业管理与ERP》课程介绍 (43)34. 《软件工程B》课程介绍 (44)35. 《软件质量与测试基础》课程介绍 (45)36. 《网络协议分析与设计》课程介绍 (46)37. 《物流与供应链管理》课程介绍 (47)38. 《网络性能测试与分析》课程介绍 (48)39. 《信息系统分析与设计》课程介绍 (49)40. 《现代通信技术》课程介绍 (50)41. 《计算机网络基础》课程介绍 (51)42. 《计算机组成与体系结构》课程介绍 (53)43. 《运筹学B》课程介绍 (54)44. 《大型数据库系统基础》课程介绍 (55)1.《算法设计与分析》课程介绍2)教学目的和要求算法设计与分析是计算机科学与技术专业的专业课程,在计算机科学与应用的理论研究中具有重要的地位。
分治算法设计(求第K个最小数)
福建工程学院计算机与信息科学系实验报告2010 – 2011 学年第一学期任课老师:实验题目1.设计程序利用分治策略求n个数的最大值和最小值。
2.利用分治策略,在n个不同元素中找出第k个最小元素。
实验时间实验开始日期:报告提交日期:实验目的、要求一、算法设计技术当我们求解某些问题时,由于这些问题要处理的数据相当多,或求解过程相当复杂,使得直接求解法在时间上相当长,或者根本无法直接求出。
对于这类问题,我们往往先把它分解成几个子问题,找到求出这几个子问题的解法后,再找到合适的方法,把它们组合成求整个问题的解法。
如果这些子问题还较大,难以解决,可以再把它们分成几个更小的子问题,以此类推,直至可以直接求出解为止。
这就是分治策略的基本思想。
下面通过实例加以说明。
【例】在n个元素中找出最大元素和最小元素。
我们可以把这n个元素放在一个数组中,用直接比较法求出。
算法如下:void maxmin1(int A[],int n,int *max,int *min){ int i;*min=*max=A[0];for(i=2;i < n;i++){ if(A[i] > *max) *max= A[i];if(A[i] < *min) *min= A[i];}}上面这个算法需比较2(n-1)次。
能否找到更好的算法呢?我们用分治策略来讨论。
把n个元素分成两组:A1={A[1],...,A[int(n/2)]}和A2={A[int(N/2)+1],...,A[N]}分别求这两组的最大值和最小值,然后分别将这两组的最大值和最小值相比较,求出全部元素的最大值和最小值。
如果A1和A2中的元素多于两个,则再用上述方法各分为两个子集。
直至子集中元素至多两个元素为止。
例如有下面一组元素:-13,13,9,-5,7,23,0,15。
用分治策略比较的过程如下:图中每个方框中,左边是最小值,右边是最大值。
从图中看出,用这种方法一共比较了10次,比直接比较法的14次减少4次,即约减少了1/3。
2.分治法
计算机学院
甘靖
2014-5-21
- 计算机算法基础 -
二次取中间值
计算机学院
甘靖
2014-5-21
- 计算机算法基础 -
算法时间复杂度分析
最坏情况下
T(n)cn if n24
T(n)T(n/5)+T(3n/4)+cn T(n) 20cn
计算机学院
甘靖
2014-5-21
- 计算机算法基础 -
summary
Divide-and-Conquer
A problem’s instance is divided into several smaller instances of the same problem, ideally of about the same size. The smaller instances are solved. If necessary, the solutions obtained for the smaller instances are combined to get a solution to the original problem.
计算机学院
甘靖
2014-5-21
- 计算机算法基础 -
五、 选择问题
方案一: 先用排序算法排序,然后输出第k个元素 算法复杂度O(nlog2n) 要排序整个l-5-21
- 计算机算法基础 -
方案二: 不必排序整个list,只需排序包含kth最小元的子集
A[j] A[j]
平均情况下(和下面递归式有相同的复杂度)
T(n)=T(n/2)+(n+1) T(n)=(n)
计算机学院
甘靖
2014-5-21
分冶策略(讲课稿)
分治策略(Divide and Conquer)一、算法思想任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。
问题规模越小,解题所需的计算时间往往也越少,从而也越容易计算。
想解决一个较大的问题,有时是相当困难的。
分治法的思想就是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
分而治之方法与软件设计的模块化方法非常相似。
为了解决一个大的问题,可以:1) 把它分成两个或多个更小的问题;2) 分别解决每个小问题;3) 把各小问题的解答组合起来,即可得到原问题的解答。
小问题通常与原问题相似,可以递归地使用分而治之策略来解决。
1、解决算法实现的同时,需要估算算法实现所需时间。
分治算法时间是这样确定的:解决子问题所需的工作总量(由子问题的个数、解决每个子问题的工作量决定)合并所有子问题所需的工作量。
2、分治法是把任意大小问题尽可能地等分成两个子问题的递归算法3、分治的具体过程:begin {开始}if ①问题不可分then ②返回问题解else begin③从原问题中划出含一半运算对象的子问题1;④递归调用分治法过程,求出解1;⑤从原问题中划出含另一半运算对象的子问题2;⑥递归调用分治法过程,求出解2;⑦将解1、解2组合成整修问题的解;end;end; {结束}二、分治策略的应用(1)二分搜索(折半查找)算法思想:将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小于该中点元素,则将待查序列缩小为左半部分,否则为右半部分。
通过一次比较,将查找区间缩小一半。
折半查找是一种高效的查找方法。
它可以明显减少比较次数,提高查找效率。
但是,折半查找的先决条件是查找表中的数据元素必须有序。
算法步骤描述:step1 首先确定整个查找区间的中间位置:mid = (left + right )/ 2step2 用待查关键字值与中间位置的关键字值进行比较;●若相等,则查找成功●若大于,则在后(右)半个区域继续进行折半查找●若小于,则在前(左)半个区域继续进行折半查找Step3 对确定的缩小区域再按折半公式,重复上述步骤。
二分治专题座PPT课件
时间复杂度
令t(n)表示MaxMin需要的元素比较次数, 存在下列递推关系
0
n1
t(n)
1
n2
t(n/2)t(n/2)2 n2
当n是2的幂时, 即对于某个正整数k, n=2k, 有
t(n)=2t(n/2)+2 = 2(2t(n/4)+2)+2 = 4t(n/4)+4+2
=2k-1t(2)+
2i
=2k-1+2k-2 1ik 1
else b[k++]=a[h++]; } if(l>mid)
while (h<=high) b[k++]=a[h++]; /* 转储剩余部分 */ else
while(l<=mid) b[k++]=a[l++]; a[low : high]=b[low : high]; /* 将b数组转储到a */ }
已分类的部分
未分类的部分
a[1] … a[j-1] a[j] a[j+1] … a[n]
插入分类算法
InsertSort(int n) { for(j=1; j<n; j++)
{ for( unsorted=a[j], k=j-1; (k>=0)&&(unsorted <a[k]); k-- ) a[k+1]=a[k];
a[k+1]= unsorted; } }
时间复杂度
考虑内层for循环中元素比较的次数T(n)
最好情况: 最坏情况:
T(n)=O(n) T(n)==1+2+…n-1==O(n2)
分治算法探讨分治策略与应用场景
分治算法探讨分治策略与应用场景随着计算机科学的快速发展,算法成为了解决问题的重要工具。
其中,分治算法在很多场景下展现出强大的能力,被广泛应用于各个领域。
本文将探讨分治策略的原理和常见应用场景。
一、分治策略的基本原理分治策略是一种将大问题划分为细分的子问题,并通过解决子问题来解决原始问题的思想。
其基本思路可以概括为以下三个步骤:1. 分解:将原始问题划分为若干规模较小的子问题。
2. 解决:递归地解决各个子问题。
3. 合并:将各个子问题的解合并为原始问题的解。
通过将大问题递归地划分为越来越小的子问题,最终解决各个子问题,再将子问题的解合并为原始问题的解,分治策略能够高效地解决很多复杂的问题。
二、分治策略的应用场景1. 排序算法排序是计算机科学中一个重要的问题,各种排序算法都可以使用分治策略来实现。
例如,快速排序和归并排序就是使用分治策略的经典排序算法。
在快速排序中,通过选择一个基准元素将问题划分为两个子问题,然后递归地排序子问题。
最后,再将排序好的子数组合并为原始数组的有序序列。
在归并排序中,通过将问题划分为两个子问题,递归地排序子数组。
最后,再将排序好的子数组合并为原始数组的有序序列。
归并排序的特点是稳定性好,适用于大规模数据的排序。
2. 查找问题分治策略也可以应用于查找问题。
例如,在有序数组中查找某个元素可以使用二分查找算法,该算法也采用了分治思想。
二分查找算法通过将问题划分为两个子问题,然后根据子问题的规模逐步缩小查找范围,最终找到目标元素。
这种分治思想使得二分查找具有高效性。
3. 矩阵乘法矩阵乘法是一个常见的数学运算问题。
通过分治策略,可以将矩阵乘法划分为多个小问题,并递归地解决这些小问题。
然后,再将这些小问题的解进行合并,得到原始问题的解。
分治法用于矩阵乘法算法的优化,可以减少运算量,提高计算效率。
4. 搜索问题分治策略也可以应用于搜索问题。
例如,在搜索引擎中,分治策略可以用于并行搜索,从而加快搜索速度。
算法设计与分析:第02章 递归与分治策略
2.1
递归的概念
例4 排列问题 设计一个递归算法生成n个元素{r1,r2,…,rn}的全排列。 设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。 集合X中元素的全排列记为perm(X)。 (ri)perm(X)表示在全排列perm(X)的每一个排列前加上前 缀得到的排列。R的全排列可归纳定义如下: 当n=1时,perm(R)=(r),其中r是集合R中唯一的元素; 当n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),…, (rn)perm(Rn)构成。
分治法的基本步骤
divide-and-conquer(P) { if ( | P | <= n0) 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); //将各子问题的解合并为原问题的解 } 人们从大量实践中发现,在用分治法设计算法时,最好使 子问题的规模大致相同。即将一个问题分成大小相等的k个子问 题的处理方法是行之有效的。这种使子问题规模大致相等的做 法是出自一种平衡(balancing)子问题的思想,它几乎总是比子 问题规模不等的做法要好。
1 5 n1 1 5 n1 1 F (n) 2 5 2
但本例中的Ackerman函数却无法找到非递归的定义。
2.1
例3 Ackerman函数
递归的概念
• A(n,m)的自变量m的每一个值都定义了一个单变量函数: • M=0时,A(n,0)=n+2 • M=1时,A(n,1)=A(A(n-1,1),0)=A(n-1,1)+2,和A(1,1)=2故 A(n,1)=2*n • M=2时,A(n,2)=A(A(n-1,2),1)=2A(n-1,2),和 A(1,2)=A(A(0,2),1)=A(1,1)=2,故A(n,2)= 2^n 。
用分治法解决问题
分治法所能解决的问题具有以下几个特征:
1.该问题的规模缩小到一定的程度就可以容易地解决;
2.该问题可以分解为若干个规模较小且基本相同的子问 题。
3.利用该问题分解出的子问题的解可以合并为该问题的 解;
基本步骤
一般分为三步递归进行 1.分解:将原问题分解为若干个规模较小,相互独
分治过程
比较过程
2 2
分析
从图例可以看出,当有8个金块的时候,方法1需要 比较15-16次,方法2只需要比较10次,那么形成比 较次数差异的根据原因在哪里?
其根本原因在于方法2对金块实行了分组比较。 对于N枚金块,我可以推出比较次数的公式: 假设n是2的次幂,c(n)为所需要的比较次数。 方法1: c(n)=2n-1 方法2:c(n) = 2c(n/2 ) + 2。 由c(2)=1, 使用迭代方法可知c(n) = 3n/2 - 2。
方法1
假设袋中有n 个金块。可以用函数M a x通过n-1次比较 找到最重的金块。找到最重的金块后,可以从余下的n-1 个金块中用类似的方法通过n-2次比较找出最轻的金块。 这样,比较的总次数为2n-3。
算法如下: int max=a[1],min=a[1], i; for(i=2;i<=n;i++){ if(a[i]>max){ max=a[i]; } if(a[i]<min){ min=a[i]; } }
为了帮助你完成这一任务,将提供一台可用来比 较两组硬币重量的仪器,比如天平。利用这台仪 器,可以知道两组硬币的重量是否相同。
方法1
任意取1枚硬币,与其他硬币进行比较,若发现轻 者,这那枚为伪币。最多可能有15次比较。
分治算法详解及经典例题
分治算法详解及经典例题⼀、基本概念在计算机科学中,分治法是⼀种很重要的算法。
字⾯上的解释是“分⽽治之”,就是把⼀个复杂的问题分成两个或更多的相同或相似的⼦问题,再把⼦问题分成更⼩的⼦问题……直到最后⼦问题可以简单的直接求解,原问题的解即⼦问题的解的合并。
这个技巧是很多⾼效算法的基础,如排序算法(快速排序,归并排序),傅⽴叶变换(快速傅⽴叶变换)……任何⼀个可以⽤计算机求解的问题所需的计算时间都与其规模有关。
问题的规模越⼩,越容易直接求解,解题所需的计算时间也越少。
例如,对于n个元素的排序问题,当n=1时,不需任何计算。
n=2时,只要作⼀次⽐较即可排好序。
n=3时只要作3次⽐较即可,…。
⽽当n较⼤时,问题就不那么容易处理了。
要想直接解决⼀个规模较⼤的问题,有时是相当困难的。
⼆、基本思想及策略分治法的设计思想是:将⼀个难以直接解决的⼤问题,分割成⼀些规模较⼩的相同问题,以便各个击破,分⽽治之。
分治策略是:对于⼀个规模为n的问题,若该问题可以容易地解决(⽐如说规模n较⼩)则直接解决,否则将其分解为k个规模较⼩的⼦问题,这些⼦问题互相独⽴且与原问题形式相同,递归地解这些⼦问题,然后将各⼦问题的解合并得到原问题的解。
这种算法设计策略叫做分治法。
如果原问题可分割成k个⼦问题,1<k≤n,且这些⼦问题都可解并可利⽤这些⼦问题的解求出原问题的解,那么这种分治法就是可⾏的。
由分治法产⽣的⼦问题往往是原问题的较⼩模式,这就为使⽤递归技术提供了⽅便。
在这种情况下,反复应⽤分治⼿段,可以使⼦问题与原问题类型⼀致⽽其规模却不断缩⼩,最终使⼦问题缩⼩到很容易直接求出其解。
这⾃然导致递归过程的产⽣。
分治与递归像⼀对孪⽣兄弟,经常同时应⽤在算法设计之中,并由此产⽣许多⾼效算法。
三、分治法适⽤的情况分治法所能解决的问题⼀般具有以下⼏个特征:1) 该问题的规模缩⼩到⼀定的程度就可以容易地解决2) 该问题可以分解为若⼲个规模较⼩的相同问题,即该问题具有最优⼦结构性质。
算法分析与设计第四章2分治法归并分类PPT课件
{
item=a[j];i=j-1;
while(i>=1&&item<a[i])
{
a[i+1]=a[i];i=i-1;
}
a[i+1]=item;
}
}
2008-09-01
i指示的是j之前的一位, 即当前已排序子表的 最末一个元素的下标
4
性能分析
输入数据按非增次序排列,每次内层while循 环执行j次(j=1,2,…, n-1)。
i 1 2 3 4 5 6 7 8 9 10 a[i] 6 7 8 9 2 3 4 5 0 1
i 1 2 3 4 5 6 7 8 9 10 a[i] 2 3 4 5 6 7 8 9 0 1
步骤4:length=8
i 1 2 3 4 5 6 7 8 9 10 a[i] 0 1 2 3 4 5 6 7 8 9
16
public static void MergeSort(int n,int DataLength) { //n为待合并数据个数
int i,t; //循环计数变量 i=1; //还有两段长度为DataLength的list可合并 while(i<=(n-2*DataLength+1)) {
Merge(i, i+DataLength-1, i+2*DataLength-1); i=i+2*DataLength; } if(i+DataLength<n) {//合并两段list,一段长度为DataLength,另一段长度不足DataLength Merge(i, i+DataLength-1, n); } else {//将剩下一段长度不足DataLength的list中的值不变 } }
分治算法简介及习题选讲
方法一
• • • • • • • • • • • 枚举:枚举i和j,再计算Ai+Ai+1+...+Aj。程序如下: max:=a[1]; for i:=1 to n-1 do begin for j:=i to n do begin s:=0; for k:=i to j do inc(s,a[k]); if s>max then max:=s end; end; writeln(max); 时间复杂度为O(n3),当n较大时会超时。
方法四
• 跟方法三一样,首先把n个数从小到大排序,跟方法三处理方法不同的是分 别求出两个下标: 1.low(a)表示>=a的最小下标;2.high(b)表示<=b的最大下标 答案就是high(b)-low(a)+1。其中high(b)跟方法三中的num(b)求法一样。 • 计算low[a]也是采用二分法,会因要求不同程序有所变动,程序如下,其中left 或right+1最终值就是low(a): left:=1;right:=n; while left<=right do begin mid:=(left+right)shr 1; if x[mid]<a then left:=mid+1 else right:=mid-1; end实际情况,只要分析 好right=left+1和left=right的情况就能保证不出错。 • 方法四时间复杂度为O((n+m)lgn)。
方法一
• 枚举法 • 设f[x]=ax3+bx2+cx+d,从-100.00到100.00以 0.01的步长逐一枚举x并代入f[x],找出最接近0 的三个f[x],其对应的x就是答案。
分治算法的思想是什么有哪些经典应用
分治算法的思想是什么有哪些经典应用在计算机科学领域,分治算法是一种非常重要的算法设计策略。
它的基本思想是将一个复杂的问题分解成若干个规模较小、相互独立且与原问题形式相同的子问题,然后分别求解这些子问题,最后将子问题的解合并起来,得到原问题的解。
分治算法的核心在于“分”和“治”这两个关键步骤。
“分”就是将原问题划分为若干个子问题,每个子问题的规模都比原问题小。
这个划分过程需要保证子问题之间相互独立,也就是说,解决一个子问题不会影响到其他子问题的解决。
“治”则是对每个子问题进行求解。
如果子问题的规模仍然较大,无法直接求解,那么可以继续对其进行分解,直到子问题的规模足够小,可以直接求解为止。
分治算法之所以有效,是因为它充分利用了问题的结构特征,将一个复杂的大问题转化为多个简单的小问题,从而降低了问题的复杂度。
同时,通过合理的分解和合并策略,可以有效地减少计算量和时间复杂度。
接下来,让我们看看分治算法在实际中的一些经典应用。
归并排序归并排序是分治算法的一个典型应用。
它的基本思想是将待排序的数组分成两半,对每一半分别进行排序,然后将排序好的两半合并起来。
具体来说,首先将数组分成左右两部分,然后对左右两部分分别进行归并排序。
当左右两部分都排序完成后,使用一个额外的辅助数组来合并这两部分。
在合并过程中,比较左右两部分的元素,将较小的元素依次放入辅助数组中,直到其中一部分的元素全部放入辅助数组。
最后,将辅助数组中的元素复制回原数组,完成排序。
归并排序的时间复杂度为 O(nlogn),空间复杂度为 O(n)。
它是一种稳定的排序算法,即相同元素的相对顺序在排序前后保持不变。
快速排序快速排序也是一种基于分治思想的排序算法。
它首先选择一个基准元素,将数组中小于基准元素的元素放在左边,大于基准元素的元素放在右边,然后对左右两部分分别进行快速排序。
选择基准元素的方法有很多种,比如选择数组的第一个元素、中间元素或者随机选择一个元素。
分治算法PPT
第一步
[38 49] [65 97] [13 76] [27]
第二步 第三步
[38 49 65 97]
[13 27 76]
18
[13 27 38 49 65 76 97]
归并排序主函数
void mergesort(int A[], int l, int r, int T[]) {
if(l < r) { int mid = (l + r) / 2; //二分 mergesort(A, l, mid, T);//继续对左子序列递归排序 mergesort(A, mid+1, r, T);//继续对右子序列递归排序 merge(A, l, mid, r, T); //合并
8
方法1
假设袋中有n个金块。可以通过n-1次比较找到最重 的金块。然后可以从余下的n-1个金块中用类似的方 法通过n-2次比较找出最轻的金块。这样,比较的总 次数为2n-3。具体的实现方法如下:
max = a[1]; min = a[1]; for(i=2; i<=n; i++) //2n-2次比较 {
问题,最后合并其结果就得到原问题的解。当分解(Divide):将原问题分成一系列子问题。 解决(Conquer):递归地解各子问题。若子问题
足够小,则可直接求解。 合并(combine);将子问题的结果合并成原问题
的解。
14
分治思想
问题的分解
方法1:每枚硬币都至少进行了一次比较,而有一枚硬 币进行了15次比较
方法2:每一枚硬币只进行了一次比较 方法3:将硬币分为两组后一次比较可以将硬币的范
围缩小到了原来的一半,这样充分地利用了只有1枚 伪币的基本性质。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
left
1 14
2 17
3 21
4 27
5 31
6 38
7 42
8 46
9 53
10 75
right
7
middle
二分搜索算法的基本思想是将n个元素分成个数大致相 同的两半,取a[n/2]与x作比较。
如果x=a[n/2],则找到x,算法终止。 如果x<a[n/2],则我们只要在数组a的左半部分继续搜索x。 如果x>a[n/2],则我们只要在数组a的右半部分继续搜索x。
12
3.2.5 棋盘覆盖问题
在一个 2k×2k个方格组成的棋盘中,若恰有一个方格与其他方格不 同,称该方格为特殊方格,且称该棋盘为特殊棋盘(Defective Chessboard)。
特殊方格在棋盘中出现的位置有 4k种情形,就有4k种不同的棋盘。
图中的特殊棋盘是当 k=2时16个特殊棋盘中一个。在棋盘覆盖问题 中,要求用图所示的4种不同形状的L型骨牌覆盖给定棋盘上除特殊 方格以外的所有方格,且任何两个L型骨牌不得重叠覆盖。在任何一 个个 2k×2k的棋盘覆盖中,用到的L型骨牌个数为 (4k-1)/3。
2
分治策略
分治策略是对于一个规模为n的问题,若该问题可以 容易地解决(比如说规模n较小)则直接解决,否则 将其分解为k个规模较小的子问题,这些子问题互相 独立且与原问题形式相同。 递归地解这些子问题,然后将各子问题的解合并得 到原问题的解。
3
3.2.1 分治法的基本步骤
分治法在每一层递归上都有三个步骤:
15
棋盘覆盖问题的分治算法
16
3.2.6 选择问题
对于给定的n个元素的数组a[0:n—1],要求从中找出第 k小的元素。 输入
输入有多组测试例。 对每一个测试例有2行,第一行是整数n和k(1≤k<n≤1000), 第二行是n个整数。
输出
第k小的元素。
输入样例 52 39416 73 4 59 7 23 61 55 46 输出样例 3 23
9
3.2.4循环赛日程表
1 2 1 3 4 4 3 5 6 6 5 7 8 8 7
1
2 3 4 5
2
1 4 3 6
3
4 1 2 7
4
3 2 1 8
5
6 7 8 1
6
7 8 5 4
7
8 5 6 3
8
5 6 7 2
第1天, 1与2比, 2与1比
1
天数 ①
2
3
4 2 1 4 3 3 4 1 2 4 3 2 1 5 6 7 8
do…while语句: 当条件为true时继续 循环的处理过程
≥
输入样例 52 39416
left
输出样例 3
right
3 9 4 1 6
pivot i
j right
left
3 9 4 1 6
pivot i j
21
3.2.7输油管道问题
某石油公司计划建造一条由东向西的主输油管道。该管道 要穿过一个有n口油井的油田。从每口油井都要有一条输 油管道沿最短路经(或南或北)与主管道相连。 如果给定n口油井的位置,即它们的x坐标(东西向)和y 坐标(南北向),应如何确定主管道的最优位置,即使各 油井到主管道之间的输油管道长度总和最小的位置? 给定n口油井的位置,编程计算各油井到主管道之间的输 油管道最小长度总和。
1
递归与分治策略
任何一个可以用计算机求解的问题所需的计算时间都与其规 模n有关。问题的规模越小,越容易直接求解,解题所需的 计算时间也越少。 分治法的设计思想是,将一个难以直接解决的大问题,分割 成一些规模较小的相同问题,以便各个击破,分而治之。 如果原问题可分割成k个子问题(1<k≤n),且这些子问 题都可解,并可利用这些子问题的解求出原问题的解,那么 这种分治法就是可行的。 由分治法产生的子问题往往是原问题的较小模式,这就为使 用递归技术提供了方便。
输入样例 52 39416 输出样例 3 1 3 9 4 6
此算法在最坏情况时间复杂度为 O(n2) , 此时nleft总是为0,左子集为空,即第 k小元素总是位于right子集中。 平均时间复杂度为 O(n )。
20
算法3.9 采用分治策略 找出第K小元素的算法
i=1 j=3 31496 i=2 j=1 j=1 left=0 3
4
3.2.1 分治法的基本步骤
根据分治法的分割原则,原问题应该分为多少个子问题才 较适宜?各个子问题的规模应该怎样才为适当?这些问题 很难予以肯定的回答。 在用分治法设计算法时,最好使子问题的规模大致相同。 如分成大小相等的k个子问题,许多问题可以取k=2。 这种使子问题规模大致相等的做法是出自一种平衡 (Balancing)子问题的思想,它几乎总是比子问题规模 不等的做法要好。
记一趟快速排序后,分解出左子集中元素个数为 nleft,则选 择问题可能是以下几种情况之一: ① nleft =k﹣1,则分界数据就是选择问题的答案。 ② nleft >k﹣1,则选择问题的答案继续在左子集中找, 问题规模变小了。 ③ nleft <k﹣1,则选择问题的答案继续在右子集中找, 问题变为选择第k-nleft-1 小的数,问题的规模变小了。
算法3.6 二分搜索算法 //数组a[]中有n个元素,已经按升序排序,待查找的元素x template<class Type> int BinarySearch(Type a[],const Type& x,int n) { int left=0; //左边界 int right=n-1; //右边界 while(left<=right) { int middle=(left+right)/2; //中点 if (x==a[middle]) return middle; if (x>a[middle]) left=middle+1; else right=middle-1; } return -1; //未找到x }
22
3.2.7输油管道问题
输入
第1行是一个整数n,表示油井的数量(1≤n≤10 000)。 接下来n行是油井的位置,每行两个整数x和y (﹣10 000≤x,y≤10 000)。
8
3.2.4循环赛日程表
问题描述:设有n=2k个运动员要进行网球循环赛。 现要设计一个满足以下要求的比赛日程表:
1. 每个选手必须与其他n-1个选手各赛一次; 2. 每个选手一天只能参赛一次; 3. 循环赛在n-1天内结束。 请按此要求将比赛日程表设计成有n行和n-1列的一个表。 在表中的第i行,第j列处填入第i个选手在第j天所遇到的选手, 其中1≤i≤n,1≤j≤n-1。
1. 分解:将原问题分解为若干个规模较小,相互独立,与原问题 形式相同的子问题; 2. 解决:若子问题规模较小而容易被解决则直接解,否则递归地 解各个子问题; 3. 合并:将各个子问题的解合并为原问题的解。
算法3.5 分治策略的算法设计模式 Divide_and_Conquer(P) { if (|P|<=n0 ) return adhoc(P); divide P into smaller substances P1,P2,…,Pk; for (i=1; i<=k; k++) yi=Divide-and-Conquer(Pi) //递归解决Pi Return merge(y1,y2,…,yk) //合并子问题 }
4
3 6 5 8 7
1
2 7 8 5 6
2
1 8 7 6 5
7
8 1 2 3 4
8
7 2 1 4 3
5
6 3 4 1 2
6
5 4 3 2 1
2 3 4
6
7 8
5
8 7
8
5 6
7
6 5
2
3 4
1
2 3
4
1 2
3
4 1
1 2
2 1
教材中的表格有误
1个选手
4个选手
8个选手
每个选手必须与其他n-1个选手各赛一次; 每个选手一天只能参赛一次; 循环赛在n-1天内结束。
14
采用分治算法解决棋盘覆盖问题的数据结构
令size=2k ,表示棋盘的规格。 1. 棋盘:使用二维数组表示:
int board[1025][1025]; 为了方便递归调用,将数组board设为全局变量。board[0][0]是棋 盘的左上角方格。
2. 子棋盘:由棋盘左上角的坐标tr,tc和棋盘大小s表示。 3. 特殊方格:在二维数组中的坐标位置是(dr,dc)。 4. L型骨牌:用到的L型骨牌个数为(4k-1)/3 ,将所有L型骨牌从 1开始连续编号,用一个全局变量表示: static int tile=1;
5
3.2.2 分治法的适用条件
分治法所能解决的问题一般具有以下几个特征:
1. 该问题的规模缩小到一定的程度就可以容易地解决; 2. 该问题可以分解为若干个规模较小的相同问题,即该问题具有 最优子结构性质; 3. 利用该问题分解出的子问题的解可以合并为该问题的解; 4. 该问题所分解出的各个子问题是相互独立的,即子问题之间不 包含公共的子子问题。
13
3.2.5 棋盘覆盖问题
用分治策略,可以设计解棋盘覆盖问题的一个简捷算法。 分治的技巧在于如何划分棋盘,使划分后的子棋盘大小相 同,并且每个子棋盘均包含一个特殊方格,从而将原问题 分解为规模较小的棋盘覆盖问题。
当k>0时,将2k×2k的棋盘划分为4个2k-1×2k-1子棋盘。 原棋盘只有一个特殊方格,则其余3个子棋盘中没有特殊方格。 用一个L型骨牌覆盖这3个较小棋盘的会合处。从而将原问题转化 为4个较小规模的棋盘覆盖问题,以便采用递归方法求解。 递归地使用这种划分策略,直至将棋盘分割为1×1的子棋盘。