算法设计与分析 王红梅 第二版 第4章_分治法
算法设计及分析(第2版)王红梅胡明习题答案解析

return 0;
}
intmain()
{
char s1[19]="ababcabccabccacbab";
char s2[7]="abccac";
cout<< BF( s1, s2) <<endl;
return 0;
}
//KMP算法
#include<iostream>
using namespace std;
习题1
1. 图论诞生于七桥问题。出生于瑞士的伟大数学家欧拉(Leonhard Euler,1707—1783)提出并解决了该问题。七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图1.7是这条河以及河上的两个岛和七座桥的草图。请将该问题的数据模型抽象出来,并判断此问题是否有解。
3.分析以下程序段中基本语句的执行次数是多少,要求列出计算公式。
(1)基本语句2*i<n执行了n/2次
基本语句y = y + i * j执行了2/n次
一共执行次数=n/2+n/2=O(n)
(2)基本语句m+=1执行了(n/2)*n=O(n*n)
4.使用扩展递归技术求解下列递推关系式:
(1) (2)
(1) int T(int n)
++low;
b[high]=b[low];
}
b[low]=b[0];
return low;
}
void qsort(int l[],int low,int high)
{
int prvotloc;
算法设计与分析第四章课件

}
若被检查的活动i的开始时间Si小于最近选择 的活动j的结束时间fi,则不选择活动i,否则 选择活动i加入集合A中。
由于输入的活动以其完成时间的非减序排列, 所以算法每次总是选择具有最早完成时间的相 容活动加入集合A中。直观上,按这种方法选 择相容活动为未安排活动留下尽可能多的时间。 也就是说,该算法的贪心选择的意义是使剩余 的可安排时间段极大化,以便安排尽可能多的 相容活动。 算法的效率极高。当输入的活动已按结束时间 的非减序排列,算法只需θ (n)的时间安排n个 活动,使最多的活动能相容地使用公共资源。 如果所给出的活动未按非减序排列,可以用 θ (nlogn)的时间重排。
贪心算法的基本要素
最优子结构
当一个问题的最优解包含其子问题的最优解 时,称此问题具有最优子结构性质。问题的 最优子结构性质是该问题可用动态规划算法 或贪心算法求解的关键特征。
贪心算法与动态规划算法的差异
贪心算法和动态规划算法都要求问题具 有最优子结构性质,这是两类算法的一 个共同点。但是,对于具有最优子结构 的问题应该选用贪心算法还是动态规划 算法求解?是否能用动态规划算法求解的 问题也能用贪心算法求解?
1 i n
All 0
All 0
因此,(y1,y2,…,yn)是一个满足贪心选择性质的最优解。
然后,证明该问题具有最优子结构性质。
设(x1,x2,…,xn)是最优装载问题的一个满足贪心选择 性质的最优解,则x1=1,(x2,…,xn)是轮船载重为cw1且待装船集装箱为{2,3,…,n}时相应最优装载问 题的一个最优解。
算法设计与分析第二版课后习题解答

算法设计与分析基础课后练习答案习题1.14.设计一个计算的算法,n是任意正整数。
除了赋值和比较运算,该算法只能用到基本的四则运算操作。
算法求//输入:一个正整数n2//输出:。
step1:a=1;step2:若a*a<n 转step3,否则输出a;step3:a=a+1转step 2;5. a.用欧几里德算法求gcd(31415,14142)。
b. 用欧几里德算法求gcd(31415,14142),比检查min{m,n}和gcd(m,n)间连续整数的算法快多少倍?请估算一下。
a. gcd(31415,14142) = gcd(14142,3131) = gcd(3131, 1618) =gcd(1618, 1513) = gcd(1513, 105) = gcd(1513, 105) = gcd(105, 43) =gcd(43, 19) = gcd(19, 5) = gcd(5, 4) = gcd(4, 1) = gcd(1,0) = 1.b.有a可知计算g cd(31415,14142)欧几里德算法做了11次除法。
连续整数检测算法在14142每次迭代过程中或者做了一次除法,或者两次除法,因此这个算法做除法的次数鉴于1·14142和2·14142之间,所以欧几里德算法比此算法快1·14142/11 ≈1300 与2·14142/11 ≈2600 倍之间。
6.证明等式gc d(m,n)=gcd(n,m mod n)对每一对正整数m,n都成立.Hint:根据除法的定义不难证明:●如果d整除u和v, 那么d一定能整除u±v;●如果d整除u,那么d也能够整除u的任何整数倍k u.对于任意一对正整数m,n,若d能整除m和n,那么d一定能整除n和r=m mod n=m-qn;显然,若d能整除n和r,也一定能整除m=r+qn和n。
算法设计与分析基础第2版清华出版社ch4分治法-02

return -1
• 折半查找效率分析: • 基本操作:比较 • 最坏情况下,比较次数
C(n)=C( n/2)+1
C(1)=1
设n=2 k ,可解得
C(n)=k+1=log2n+1 • 于是
C(n)∈Θ(log2n)
折半查找举例:
//s是中轴元素/基准点,是数组分区位置的标志 中轴元素如何选?
数组的分区算法:
• 算法 Partition( A[l..r] ) // 输入:子数组A[l..r] // 输出:分裂点/基准点pivot的位置 p ← A[l] i ← l; j ← r+1 repeat repeat i ←i + 1 until A[i] ≥ p repeat j ← j – 1 until A[j] ≤ p swap( A[i], A[j] ) until i ≥ j swap( A[i], A[j] ) swap( A[l], A[j] ) return j
• 其中,f(n)是一个函数,表示将问题分解为
小问题和将结果合并起来所消耗时间(对 于求和的例子来说,a=b=2, f(n)=1)。该 递推式被称为通用分治递推式。
主定理 如果在递推式中f(n)∈⊙(n),其中 d>=0,那么:
⊙(n)
当a<b时
T(n)∈
⊙(nlog n) 当a=b时
⊙(n) 当a> b时
• 有了上面的中序遍历的过程,前序遍历也是类似 的。在遍历以前首先确定遍历的树是否为空,如 果为空,则直接返回;否则前序遍历的算法步骤 如下: (1)访问输出根结点V的值; (2)对左子树L执行前序遍历算法。 (3)对右子树R执行前序遍历算法。
算法分析实验指导书(王红梅)

《算法设计与分析》实验指导书计算机科学与技术学院石少俭实验一分治法1、实验目的(1)掌握设计有效算法的分治策略。
(2)通过快速排序学习分治策略设计技巧2、实验要求(1)熟练掌握分治法的基本思想及其应用实现。
(2)理解所给出的算法,并对其加以改进。
3、分治法的介绍任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。
问题的规模越小,越容易直接求解,解题所需的计算时间也越少。
而当n较大时,问题就不那么容易处理了。
要想直接解决一个规模较大的问题,有时是相当困难的。
分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
如果原问题可分割成k个子问题,1<k≤n ,且这些子问题都可解,并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。
由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
分治法的适用条件(1)该问题的规模缩小到一定的程度就可以容易地解决;(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
(3)利用该问题分解出的子问题的解可以合并为该问题的解;(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。
上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提,它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑贪心法或动态规划法。
第四条特征涉及到分治法的效率,如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
算法设计与分析(第2版)-王红梅-胡明-习题答案(1)

算法设计与分析(第2版)-王红梅-胡明-习题答案习题11. 图论诞生于七桥问题。
出生于瑞士的伟大数学家欧拉(Leonhard Euler ,1707—1783)提出并解决了该问题。
七桥问题是这样描述的:一个人是否能在一次步行中穿越哥尼斯堡(现在叫加里宁格勒,在波罗的海南岸)城中全部的七座桥后回到起点,且每座桥只经过一次,图 1.7是这条河以及河上的两个岛和七座桥的草图。
请将该问题的数据模型抽象出来,并判断此问题是否有解。
七桥问题属于一笔画问题。
输入:一个起点输出:相同的点1, 一次步行2, 经过七座桥,且每次只经历过一次3, 回到起点该问题无解:能一笔画的图形只有两类:一类是所有的点都是偶点。
另一类是只有二个奇点的图形。
2.在欧几里德提出的欧几里德算法中(即最初的欧几里德算法)用的不是除法而是减法。
请用伪代码描述这个版本的欧几里德算法1.r=m-n2.循环直到r=02.1 m=n图1.7 七桥问题2.2 n=r2.3 r=m-n3 输出m3.设计算法求数组中相差最小的两个元素(称为最接近数)的差。
要求分别给出伪代码和C++描述。
//采用分治法//对数组先进行快速排序//在依次比较相邻的差#include <iostream>using namespace std;int partions(int b[],int low,int high){int prvotkey=b[low];b[0]=b[low];while (low<high){while (low<high&&b[high]>=prvotkey)--high;b[low]=b[high];while (low<high&&b[low]<=prvotkey)++low;b[high]=b[low];}b[low]=b[0];return low;}void qsort(int l[],int low,int high){int prvotloc;if(low<high){prvotloc=partions(l,low,high); //将第一次排序的结果作为枢轴qsort(l,low,prvotloc-1); //递归调用排序由low 到prvotloc-1qsort(l,prvotloc+1,high); //递归调用排序由 prvotloc+1到 high}}void quicksort(int l[],int n){qsort(l,1,n); //第一个作为枢轴,从第一个排到第n个}int main(){int a[11]={0,2,32,43,23,45,36,57,14,27,39};int value=0;//将最小差的值赋值给valuefor (int b=1;b<11;b++)cout<<a[b]<<' ';cout<<endl;quicksort(a,11);for(int i=0;i!=9;++i){if( (a[i+1]-a[i])<=(a[i+2]-a[i+1]) )value=a[i+1]-a[i];elsevalue=a[i+2]-a[i+1];}cout<<value<<endl;return 0;}4.设数组a[n]中的元素均不相等,设计算法找出a[n]中一个既不是最大也不是最小的元素,并说明最坏情况下的比较次数。
算法设计与分析王红梅第二版动态规划详解演示文稿

2022/3/2
Chapter 6 Dynamic Programming
26
第26页,共110页。
多段图的最短路径问题
多段图的决策过程:
多段图的边(u, v),用cuv 表边的权值,从源点s到终点t的最短路 径记为d(s, t),则从源点0到终点9的最短路径d(0, 9)由下式确定 :
d(0, 9)=min{c01+d(1, 9), c02+d(2, 9), c03+d(3, 9)}
2022/3/2
Chapter 6 Dynamic Programming
10
第10页,共110页。
动态规划法的设计思想
动态规划法的求解过程 原问题
子问题1
子问题2 ……
子问题n
2022/3/2
填表 原问题的解
Chapter 6 Dynamic Programming
11
第11页,共110页。
动态规划法的设计思想
Page 15
第6章 动态规划法
2022/3/2
第15页,共110页。
数塔问题——想法
[想法]从顶层出 发下一层选择 取决于两个4层 数塔的最大数 值和。
8 12 15 3 96 8 10 5 12 16 4 18 10 9
Page 16
第6章 动态规划法
2022/3/2
第16页,共110页。
数塔问题——想法
求解初始子问题:底层的每个数字可看作1层数塔,则最大数值和就是其自身; 再求解下一阶段的子问题:第4层的决策是在底层决策的基础上进行求解,可以看作4 个2层数塔,对每个数塔进行求解; 再求解下一阶段的子问题:第3层的决策是在第4层决策的基础上进行求解,可以看作3个 2层的数塔,对每个数塔进行求解;
算法设计与分析-总结0

这本书是《算法设计与分析》王红梅编著一共有以下12章,我们学了1、3、4、5、6、7、8、9分别是“绪论、蛮力法、分治法、减治法、动态规划法、贪心法、回溯法、分治限界法第1章绪论考点:1、算法的5个重要特性。
(P3)答:输入、输出、有穷性、确定性、可行性2、描述算法的四种方法分别是什么,有什么优缺点。
(P4)答:1. 自然语言优点:容易理解;缺点:容易出现二义性,并且算法都很冗长。
2. 流程图优点:直观易懂;缺点:严密性不如程序语言,灵活性不如自然语言。
3. 程序设计语言优点:用程序语言描述的算法能由计算机直接执行;缺点:抽象性差,是算法设计者拘泥于描述算法的具体细节,忽略了“好”算法和正确逻辑的重要性,此外,还要求算法设计者掌握程序设计语言及其编程技巧。
伪代码优点:表达能力强,抽象性强,容易理解3、了解非递归算法的时间复杂性分析。
(P13)要点:对非递归算法时间复杂性的分析,关键是建立一个代表算法运行时间的求和表达式,然后用渐进符号表示这个求和表达式。
非递归算法分析的一般步骤是:(1)决定用哪个(或哪些)参数作为算法问题规模的度量。
(2)找出算法的基本语句。
(3)检查基本语句的执行次数是否只依赖问题规模。
(4)建立基本语句执行次数的求和表达式。
(5)用渐进符号表示这个求和表达式。
[例1.4]:求数组最小值算法int ArrayMin(int a[ ], int n){min=a[0];for (i=1; i<n; i++)if (a[i]<min) min=a[i];return min;}问题规模:n基本语句:a[i]<minT(n)= n-1=O(n)4、掌握扩展递归技术和通用分治递推式的使用。
(P15)扩展递归技术:通用分支递归式:5、习题1-4,习题1-7设计算法求数组中相差最小的两个元素(称为最接近数)的差。
要求给出伪代码描述,并用一组例子进行跟踪验证,写出验证过程。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本章要点
4.1 概 述 4.2 排序问题中的分治法 4.3 组合问题中的分治法 4.4 几何问题中的分治法 阅读材料 递归函数的执行过程
2015-5-2
Divide and Conquer Method
16
排序问题中的分治法
4.2.1 4.2.2
归并排序 快速排序
2015-5-2
Divide and Conquer Method
5
概述-分治法思想
启发式规则:
1. 平衡子问题:最好使子问题的规模大致相同。也就是将一 个问题划分成大小相等的k个子问题(通常k=2、4,…),这 种使子问题规模大致相等的做法是出自一种平衡(Balancing) 子问题的思想,它几乎总是比子问题规模不等的做法要好。 2. 独立子问题:各子问题之间相互独立,这涉及到分治法的 效率,如果各子问题不是独立的,则分治法需要重复地解公 共的子问题。
当n=0时 0 当n=1时 T(n) = 1 T(n-2)+4(n-1) 当n>1时
设n为偶数,用扩展递归技术解此递推式,得 T(n)=T(n-2)+4(n-1)=T(n-4)+4(n-3)+4(n-1)
=T(0)+…+4(n-5)+4(n-3)+4(n-1)=O(n2)
2015-5-2 Divide and Conquer Method 15
原问题划分成k个较小规模的子问题,对这k个子问题分别求 解。如果子问题的规模仍然不够小,则再将每个子问题划分
为k个规模更小的子问题,如此分解下去,直到问题规模足够
小,很容易求出其解为止,再将子问题的解合并为一个更大 规模的问题的解,自底向上逐步求出原问题的解。
2015-5-2
Divide and Conquer Method
2015-5-2 Divide and Conquer Method 21
4.2.1 归并排序
算法4.4——合并有序子序列 void Merge(int r[ ], int r1[ ], int s, int m, int t)
{ // i,j分别指向两个待合并的有序子序列,k指向最终有序序列的当前记录
2015-5-2
Divide and Conquer Method
8
概述-分治法的求解过程
分治法的一般过程
1 DivideConquer(P) //求解规模为n的问题P 2 { 3 if (P的规模足够小) 直接求解P; 分解为k个子问题P1, P2, …, Pk; 4 for (i=1;i<=k;i++) 5 yi=DivideConquer(P); //解各子问题,通常采用递归 6 return Merge (y1, y2, …, yk ); //将各子问题的解合并为原问题的解 7 }
2015-5-2
Divide and Conquer Method
9
例:计算an,应用分治技术得到如下计算方法:
a
时间性能 O(nlog2n) 而蛮力法的 时间性能为 O(n)
n
= n a
a n 2 * a
34
2
如果 n = 1 如果 n > 1
32 31 31 3 9 81 31 3
2015-5-2 Divide and Conquer Method 25
2015-5-2
Divide and Conquer Method
23
4.2.2 快速排序
快速排序的分治策略
( 1 )划分:选定一个记录作为轴值,以轴值为基准将整个序 列划分为两个子序列r1 … ri-1和ri+1 … rn,前一个子序列中记录 的值均小于或等于轴值,后一个子序列中记录的值均大于或等 于轴值; [ r1 … … ri-1 ] ri [ ri+1 … … rn ] (2)求解子问题:分别对 划分后的每一个子序列递归 处理; 均 ≤ri 轴值 均 ≥ri (3)合并:由于对子序列 位于最终位置 r1 … ri-1和ri+1 … rn的排序是 就地进行的,所以合并不需 要执行任何操作。
2015-5-2
Divide and Conquer Method
2
学习目标
教学重点 教学难点 教学内容 及目标 分治法的设计思想,各种经典问题的分治思想 几何问题的分治算法 知识点 了解 教学要求 理解 掌握 熟练掌 握 √ √ √ √ √
分治法设计思想
归并排序和快速排序 最大子段和问题 棋盘覆盖问题 最近对问题 凸包问题
Divide and Conquer Method
19
4.2.1 归并排序
[想法] 首先将序列划分为两个子序列,如子序列长度为 1, 则划分结束,否则继续执行划分,结果将具有 n个待排序的 记录序列划分为n个长度为1的有序子序列;然后两两合并, 得到n/2个长度为2的有序子序列,再进行两两合并…直到得 到一个长度为n的有序序列。
2015-5-2
Divide and Conquer Method
20
4.2.1 归并排序
算法4.3——归并排序 void MergeSort(int r[ ], int r1[ ], int s, int t) //r[ ]—原序列数组,r1[ ]—归并后序列数组 { if (s= =t) r1[s]=r[s]; r[s],…,r[m] r[m+1],…,r[t] else { m=(s+t)/2; Mergesort(r, r1, s, m); //归并排序前半个子序列 Mergesort(r, r1, m+1, t); //归并排序后半个子序列 Merge(r1, r, s, m, t); //合并两个已排序的子序列 } }
32 31
分解问题
求解每个子问题
3
3 9 合并子问题的解
不是所有的分治法都比简单的蛮力法更有效。
概 述
4.1.1 分治法的设计思想 4.1.2 一个简单的例子——数字旋转方阵
2015-5-2
Divide and Conquer Method
11
数字旋转方阵
[问题] 输出如图4.3(a)所示N*N(1≤N≤10)的数字旋转方阵 [思路]用二维数组表示方阵,从外层向里层填数,如图(b)所示, 将每一层的填数过程分为ABCD四个区域。每填一层size减2, 终止条件是size≤1。
2015-5-2
Divide and Conquer Method
12
数字旋转方阵
算法4.1:数字旋转方阵Full 输入:当前层左上角要填的数字number,左上角的坐标begin, 方阵的阶数size
输出:数字旋转方阵
1. 如果size=0,则算法结束; 2. 如果size=1,则data[begin][begin]=number,算法结束; 3. 初始化行、列下标i=begin,j=begin; 4. 重复下述操作size-1次,填写区域A 1. Data[i][j]=number; number++; i++;
2015-5-2 Divide and Conquer Method 18
4.2.1 归并排序
r1 … … rn/2 rn/2+1 … … rn 划分
r‘1<… …<r’n/2 r’n/2+1<… …<r’n r''1<……<r''n/2<r''n/2+1 <……<r ''n
递归处理
合并解
2015-5-2
2015-5-2 Divide and Conquer Method 13
数字旋转方阵
5. 重复下述操作size-1次,填写区域B 1. Data[i][j]=number; number++; j++; 6. 重复下述操作size-1次,填写区域C 1. Data[i][j]=number; number++; i--; 7. 重复下述操作size-1次,填写区域D
1. Data[i][j]=number; number++; j--;
8. 递归调用函数Full在size-2阶方阵中左上角begin+1处从数字 number开始填数
2015-5-2
Divide and Conquer Method
14
数字旋转方阵
[算法分析]填写n阶方阵,四个区域由4个循环实现,每个循环 均执行n-1,然后执行递归调用,填写n-2阶方阵。递推式:
2015-5-2 Divide and Conquer Method 24
4.2.2 快速排序
以第一个记录为轴值(可随机),对待排序序列进行划分的过程: ( 1 )初始化:取第一个记录作为基准,设置两个参数 i , j 分别 用来指示将要与基准记录进行比较的左侧记录位置和右侧记录位 置,也就是本次划分的区间; (2)右侧扫描过程:将基准记录与j指向的记录进行比较,如果 j指向记录的关键码大,则j--,即前移一个记录位置。重复右侧扫 描过程,直到右侧的记录小(即反序),若i<j,则将基准记录 与j指向的记录进行交换; (3)左侧扫描过程:将基准记录与i指向的记录进行比较,如果i 指向记录的关键码小,则 i++,即后移一个记录位置。重复左侧 扫描过程,直到左侧的记录大(即反序),若i<j,则将基准记 录与i指向的记录交换;
√
2015-5-2
Divide and Conquer Method
3
概 述
4.1.1 分治法的设计思想 4.1.2 分治法的求解过程
2015-5-2
Divide and Conquer Method