递归与分治
递归与分治算法心得
递归与分治算法心得
递归与分治算法都是常用的算法思想,可以很好地解决复杂问题。
递归算法是通过将问题分解为相同或相似的子问题来解决整个问题,然后再逐步合并回原问题的过程。
递归算法通常需要明确边界条件,以确保递归能够正确地停止。
分治算法是将问题分解成若干个相同或相似的子问题,递归地解决这些子问题,然后合并这些子问题的解来解决原始问题。
通常,分治算法可以高效地解决问题,但需要注意分解问题的方式和合并子问题的解的过程。
在实际应用中,递归和分治算法可以相互结合,以解决更加复杂的问题。
例如,可以使用分治算法来将问题分解成多个子问题,然后使用递归算法来解决这些子问题。
此外,还可以在递归算法中使用分治算法来对子问题进行分解和合并。
总而言之,递归与分治算法都是非常有用的算法思想,可以在许多领域中得到应用。
但是,在实际使用时,需要仔细考虑问题的性质和算法的复杂度,以确保算法的正确性和效率。
- 1 -。
递归和分治法
递归和分治法摘要:1.递归和分治法的定义2.递归和分治法的区别3.递归和分治法的应用实例4.递归和分治法的优缺点正文:递归和分治法是计算机科学中常用的两种算法设计技巧。
它们在解决问题时都采用了将问题分解成更小子问题的思路,但在具体实现上却有所不同。
下面,我们来详细了解一下递归和分治法。
1.递归和分治法的定义递归法是指在算法中调用自身来解决问题的方法。
递归函数在执行过程中,会将原问题分解成规模更小的相似子问题,然后通过调用自身的方式,解决这些子问题,最后将子问题的解合并,得到原问题的解。
分治法是指将一个大问题分解成若干个规模较小的相似子问题,然后分别解决这些子问题,最后将子问题的解合并,得到原问题的解。
分治法在解决问题时,通常需要设计一个主函数(master function)和一个子函数(subfunction)。
主函数负责将问题分解,子函数负责解决子问题。
2.递归和分治法的区别递归法和分治法在解决问题时都采用了将问题分解成更小子问题的思路,但它们在实现上存在以下区别:(1)函数调用方式不同:递归法是通过调用自身来解决问题,而分治法是通过调用不同的子函数来解决问题。
(2)递归法必须有递归出口,即必须有一个基线条件,而分治法不一定需要。
3.递归和分治法的应用实例递归法应用广泛,例如斐波那契数列、汉诺塔问题、八皇后问题等。
分治法也有很多实际应用,例如快速排序、归并排序、大整数乘法等。
4.递归和分治法的优缺点递归法的优点是代码简单易懂,但缺点是容易产生大量的重复计算,导致时间复杂度较高。
分治法的优点是时间复杂度较低,但缺点是代码实现相对复杂,需要设计主函数和子函数。
总之,递归和分治法都是解决问题的有效方法,具体应用需要根据问题的特点来选择。
递归与分治ppt课件
2023/10/8
计算机算法设计与分析
3
Hanoi塔问题的时间复杂性
n Hanoi塔问题的时间复杂性为O(2n)。 n 证明:对n归纳证明move(n) = 2n – 1。 n 归纳基础:当n = 1, move(1) = 1 = 21 – 1。 n 归纳假设:当n k, move(n) = 2n – 1。 n 归纳步骤:当n= k + 1,移动次数为
2、除法,即n / b,的形式
2023/11/4
计算机算法设计与分析
21
递归算法的时间复杂性
n 若~为减法,即n – b,则有:
T(n) = aT(n – b) + D(n)
= a(aT(n – 2b) + D(n – b)) + D(n) =
k–1
k–1
= akT(1) + ai D(n – ib) = ak + ai D(n – ib)
n q最(n简, m单)情{ 形1:(1) q(n, 1)=1, q(1, mn)==1 n或, mm≥1=;1 n 递q(iin归ff,((mnn关)<=系==1):1q1)||(|((+|nm2(,)qmm<(qn=–(1,n1=)n,)–+1n1)q))(=rrnee–1ttmuu+rr,nqnm(01n);;, nnn>–≤1m)m,>n1>1; n 产i生f (n的=新= 情1) 况|| (:n < m) return 1 + q(n, n–1); n (3r)eqtu(nr,nmq)(n=,qm(n–,1m) +–1q)(n+–qm(,nm–m);, m} ), n>m>1 n (整4)数q(nn的, m划)分= q数(nρ,(n),=nq<(nm, n。)。
(一)八大算法思想
(⼀)⼋⼤算法思想⼋⼤算法⼋⼤算法:枚举、递推、递归、分治、贪⼼、试探法、动态迭代和模拟算法思想。
⼀、枚举算法思想(暴⼒算法) 将问题的所有可能答案⼀⼀列举,根据判断条件判断此答案是否合适,⼀般⽤循环实现。
经典运⽤:百钱买百鸡、填写运算符⼆、递推算法思想 1.顺推法:从已知条件出发,逐步推算出要解决问题的⽅法。
2.逆推法:从已知结果出发,⽤迭代表达式逐步推算出问题开始的条件,即顺推法的逆过程。
经典运⽤:斐波那契数列(顺推法)、银⾏存款(逆推法)三、递归算法思想 1.递归过程⼀般通过函数或⼦过程实现; 2.递归算法在函数或⼦过程的内部,直接或间接调⽤⾃⼰的算法 3.递归算法实际上是把问题转化为规模缩⼩了的同类问题的⼦问题,然后再递归调⽤函数或过程来表⽰问题的解 注意:必须有⼀个明确的递归结束条件;如果递归次数过多,容易造成栈溢出。
经典运⽤:汉诺塔问题、阶乘问题四、分治算法思想 将⼀个规模为N的问题分解为K个规模较⼩的⼦问题,这些⼦问题相互独⽴且与原问题性质相同。
只要求出⼦问题的解,就可得到原问题的解。
⼀般步骤: 1.分解,将要解决的问题划分成若⼲个规模较⼩的同类问题 2.求解,当⼦问题划分得⾜够⼩时,⽤较简单的⽅法解决 3.合并,按原问题的要求,将⼦问题的解逐层合并构成原问题的解 经典运⽤:⼤数相乘问题、⽐赛⽇程安排五、贪⼼算法思想 从问题的某⼀个初始解出发,逐步逼近给定的⽬标,以便尽快求出更好的解。
局限: 不能保证最后的解是最优的; 不能求最⼤最⼩解问题; 只能求满⾜某些约束条件的可⾏解范围。
基本过程: 1.从问题的某⼀初始解出发 2.while能向给定总⽬标前进⼀步 3.求出可⾏解的⼀个解元素 4.由所有解元素组合成问题的⼀个可⾏解 经典运⽤:装箱问题、找零⽅案六、试探算法(回溯法) 在试探算法中,放弃当前候选解,并继续寻找下⼀个候选解的过程称为回溯。
扩⼤当前候选解的规模,以继续试探的过程称为向前试探。
计算机专业课《算法》_第二章 递归与分治策略
“Hanoi 塔”问题演示 a 初始 a 步骤1 a
c
b
c
“Hanoi 塔”问题程序
void hanoi(int n,a,b,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) ;
• 递归优点:结构清晰,可读性强
• 递归缺点:递归算法的运行效率较低,无论是耗 费的计算时间还是占用的存储空间都比非递归算 法要多。
整数划分问题的递归关系q(n,m)
如设p(n)为正整数n的划分数,则难以找到递归关系 • q(n,m):正整数n的不同的划分中,最大加数不 大于m的划分个数个数 q(n,m)=
1 q(n,n) 1+q(n,n-1) q(n,m-1)+q(n-m,m) n=1, m=1 n<m n=m n>m>1
递归函数举例(5)
学习要点
理解递归的概念。 掌握设计有效算法的分治策略。
通过典型范例,学习分治策略设计技巧。
2.1 递归的概念
• 递归算法:一个直接或间接地调用自身的算法 • 递归方程:对于递归算法,一般可把时间代 价表示为一个递归方程 • 递归函数:使用函数自身给出定义的函数 • 解递归方程最常用的方法是进行递归扩展
递归函数举例(1)
• 阶乘函数 n !=
1 n(n-1)! n=1 n>1
• Fibonacci数列
1 n=0
F(n)=
1 F(n-1)+F(n-2)
n=1 n>1
初始条件与递归方程是递归函数的二个要素
常见的程序设计方法
常见的程序设计方法程序设计是指将问题拆解为一系列可执行的指令或算法,并将其转化为计算机能够识别和执行的代码。
常见的程序设计方法包括顺序、选择、循环、递归、分治和动态规划等。
1.顺序:顺序是最简单和最常见的程序设计方法。
顺序程序设计是按照定义的顺序依次执行一系列的语句或指令,每个语句按照顺序执行,直到程序结束。
顺序程序设计常用于简单的计算和数据处理任务。
2.选择:选择是根据特定条件选择不同的执行路径。
常见的选择结构有if语句和switch语句。
if语句根据条件的真假执行不同的代码块,而switch语句根据不同的表达式值执行相应的代码块。
选择结构常用于根据用户的输入或条件的满足来决定程序的执行逻辑。
3.循环:循环是根据特定条件重复执行段代码。
常见的循环结构有while循环、do-while循环和for循环。
这些循环结构可根据循环条件的真假来确定循环的执行次数,从而实现重复执行特定操作的功能。
循环结构常用于处理大量数据或重复需要进行的任务。
4.递归:递归是指在函数或算法的实现中,调用自身来解决更小规模的同类问题。
递归算法是将一个复杂问题分解为更简单的子问题,并通过反复调用自身来解决子问题,最终达到解决原问题的目的。
递归常用于解决具有相似结构的问题,如数学问题、图形问题等。
5.分治:分治是指将问题划分成独立的子问题,对每个子问题进行求解,最后将子问题的解合并成原问题的解。
分治算法的核心思想是将复杂问题分解成多个规模较小且结构相同的子问题,并通过递归地解决这些子问题,最终得到整个问题的解。
分治算法常用于解决问题、排序问题等。
6.动态规划:动态规划是一种将问题划分为重叠子问题并缓存子问题解的方法。
与分治算法不同的是,动态规划算法会通过缓存已求解的子问题的解来避免重复计算,从而提高算法的效率。
动态规划常用于解决优化问题,如背包问题、最短路径问题等。
除以上常见的程序设计方法外,还有一些高级的方法如面向对象编程、函数式编程和事件驱动编程等。
算法之2章递归与分治
算法分析(第二章):递归与分治法一、递归的概念知识再现:等比数列求和公式:1、定义:直接或间接地调用自身的算法称为递归算法。
用函数自身给出定义的函数称为递归函数。
2、与分治法的关系:由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
分治与递归经常同时应用在算法设计之中,并由此产生许多高效算法。
3、递推方程:(1)定义:设序列01,....na a a简记为{na},把n a与某些个()ia i n<联系起来的等式叫做关于该序列的递推方程。
(2)求解:给定关于序列{n a}的递推方程和若干初值,计算n a。
4、应用:阶乘函数、Fibonacci数列、Hanoi塔问题、插入排序5、优缺点:优点:结构清晰,可读性强,而且容易用数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很大方便。
缺点:递归算法的运行效率较低,无论是耗费的计算时间还是占用的存储空间都比非递归算法要多。
二、递归算法改进:1、迭代法:(1)不断用递推方程的右部替代左部(2)每一次替换,随着n的降低在和式中多出一项(3)直到出现初值以后停止迭代(4)将初值代入并对和式求和(5)可用数学归纳法验证解的正确性2、举例:-----------Hanoi塔算法----------- ---------------插入排序算法----------- ()2(1)1(1)1T n T nT=−+=()(1)1W n W n nW=−+−(1)=021n-23()2(1)12[2(2)1]12(2)21...2++2 (121)n n n T n T n T n T n T −−=−+=−++=−++==++=−(1)2 ()(1)1((n-2)+11)1(2)(2)(1)...(1)12...(2)(1)(1)/2W n W n n W n n W n n n W n n n n =−+−=−−+−=−+−+−==++++−+−=−3、换元迭代:(1)将对n 的递推式换成对其他变元k 的递推式 (2)对k 进行迭代(3)将解(关于k 的函数)转换成关于n 的函数4、举例:---------------二分归并排序---------------()2(/2)1W n W n n W =+−(1)=0(1)换元:假设2kn =,递推方程如下()2(/2)1W n W n n W =+−(1)=0 → 1(2)2(2)21k k k W W W−=+−(0)=0(2)迭代求解:12122222321332133212()2(2)212(2(2)21)212(2)22212(2)2*2212(2(2)21)2212(2)222212(2)3*2221...2(0)*2(22...21)22k k k k k k k k k k k k k k k k k k k k k k k k W n W W W W W W W W k k −−−−−−−+−+−−−=+−=+−+−=+−+−=+−−=+−+−−=+−+−−=+−−−==+−++++=−1log 1n n n +=−+(3)解的正确性—归纳验证: 证明递推方程的解是()(1)/2W n n n =−()(1)1W n W n n W =−+−(1)=0,(n 1)=n +n=n(n-1)/2+n =n[(n-1)/2+1]=n(n+1)/2n W W +方法:数学归纳法证 n=1,W(1)=1*(1-1)/2=0假设对于解满足方程,则()---------------快速排序--------------------->>>平均工作量:假设首元素排好序在每个位置是等概率的112()()()(1)0n i T n T i O n n T −==+=∑ >>>对于高阶方程应该先化简,然后迭代(1)差消化简:利用两个方程相减,将右边的项尽可能消去,以达到降阶的目的。
算法设计与分析(霍红卫)-第2章-分治法
第2章 分 治 法
我们可以很容易解决这个问题。利用这样一个事实:渐近 表示法只要求对n≥n0,T(n)≤cn lb n成立,其中n0是一个可以选择 的常数。由于对于n>3,递归方程并不直接依赖T(1),因此可设 n0=2,选择T(2)和T(3)作为归纳证明中的边界条件。由递归方程 可得T(2)=4和T(3)=5。此时只要选择c≥2,就会使得T(2)≤c·2·lb 2 和 T(3)≤c·3·lb 3 成 立 。 因 此 , 只 要 选 择 n0=2 和 c≥2 , 则 有 T(n)≤cn lb n成立。
3ic(n/4i)2=(3/16) icn2 i=0,1,…,log4n-1
深度为log4n的最后一层有3log4 n nlog4 3 个结点,每个结点的
开销为T(1),该层总开销为 nlog4 3T (1) ,即 Θ(nlog4 3)。
第2章 分 治 法
将所有层的开销相加得到整棵树的开销:
T (n) cn2
T(n)=2T(n/2)+n ≤2(c[n/2]lb[n/2])+n =cn lb n/2+n =cn lb n-cn lb 2+n =cn lb n-cn+n =cn lb n-(c-1)n
最后一步在c≥1时成立。≤cn lb n
第2章 分 治 法
下面证明猜测对于边界条件成立, 即证明对于选择的常 数c,T(n)≤cn lb n对于边界条件成立。 这个要求有时会产生 一些问题。 假设T(1)=1是递归方程的惟一边界条件,那么对 于n=1,T(1)≤c·1·lb 1=0与T(1)=1发生矛盾。因此,归纳法中 的归纳基础不成立。
3
cn2
3
2
cn2
3
递归、分治、动态规划、回溯
n = 1, m = 1 n<m n=m n > m >1
递归举例
Hanoi塔问题 例6 Hanoi塔问题 设a,b,c是3个塔座.开始时,在塔座a上有一叠共n个圆 盘,这些圆盘自下而上,由大到小地叠在一起.各圆 盘从小到大编号为1,2,…,n,现要求将塔座a上的这一 叠圆盘移到塔座b上,并仍按同样顺序叠置.在移动圆 盘时应遵守以下移动规则: 规则1:每次只能移动1个圆盘; 规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘 之上; 规则3:在满足移动规则1和2的前提下,可将圆盘移至 a,b,c中任一塔座上.
边界条件
递归方程
A(1,0) = 2 A(0, m) = 1 m≥0 n≥2 A(n,0) = n + 2 A(n, m) = A( A(n 1, m), m 1) n, m ≥ 1
递归举例
例3 Ackerman函数 函数 当一个函数及它的一个变量是由函数自身定义时,称这 个函数是双递归函数 双递归函数. 双递归函数 Ackerman函数A(n,m) A(n, Ackerman A(n m)定义如下:
递归举例
例1 阶乘函数 阶乘函数可递归地定义为:
边界条件
n=0 1 n!= n(n 1)! n > 0
递归方程 边界条件与递归方程是递归函数的二个要素,递归函 数只有具备了这两个要素,才能在有限次计算后得出 结果.
递归举例
Fibonacci数列 例2 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,…,被 称为Fibonacci数列.它可以递归地定义为:
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 .
递推-递归-分治-回溯
递推算法在程序编辑过程中,我们可能会遇到这样一类问题,出题者告诉你数列的前几个数,或通过计算机获取了数列的前几个数,要求编程者求出第N项数或所有的数列元素(如果可以枚举的话),或求前N项元素之和。
这种从已知数据入手,寻找规则,推导出后面的数的算法,称这递推算法。
典型的递推算法的例子有整数的阶乘,1,2,6,24,120…,a[n]=a[n-1]*n(a[1]=1);前面学过的2n,a[n]=a[n-1]*2(a[1]=1),菲波拉契数列:1,2,3,5,8,13…,a[n]=a[n-1]+a[n-2](a[1]=1,a[2]=2)等等。
在处理递推问题时,我们有时遇到的递推关系是十分明显的,简单地写出递推关系式,就可以逐项递推,即由第i项推出第i+1项,我们称其为显示递推关系。
但有的递推关系,要经过仔细观察,甚至要借助一些技巧,才能看出它们之间的关系,我们称其为隐式的递推关系。
下面我们来分析一些例题,掌握一些简单的递推关系。
例如阶梯问题:题目的意思是:有N级阶梯,人可以一步走上一级,也可以一步走两级,求人从阶梯底走到顶端可以有多少种不同的走法。
这是一个隐式的递推关系,如果编程者不能找出这个递推关系,可能就无法做出这题来。
我们来分析一下:走上第一级的方法只有一种,走上第二级的方法却有两种(两次走一级或一次走两级),走上第三级的走法,应该是走上第一级的方法和走上第二级的走法之和(因从第一级和第二级,都可以经一步走至第三级),推广到走上第i级,是走上第i-1级的走法与走上第i-2级的走法之和。
很明显,这是一个菲波拉契数列。
到这里,读者应能很熟练地写出这个程序。
在以后的程序习题中,我们可能还会遇到菲波拉契数列变形以后的结果:如f(i)=f(i-1)+2f(i-2),或f(i)=f(i-1)+f(i-2)+f(i-3)等。
我们再来分析一下尼科梅彻斯定理。
定理内容是:任何一个整数的立方都可以写成一串连续的奇数和,如:43=13+15+17+19=64。
递归,分治算法,动态规划和贪心选择的区别
递归,分治算法,动态规划和贪⼼选择的区别⼀般实际⽣活中我们遇到的算法分为四类:⼀>判定性问题⼆>最优化问题三>构造性问题四>计算性问题⽽今天所要总结的算法就是着重解决最优化问题《算法之道》对三种算法进⾏了归纳总结,如下表所⽰:标准分治动态规划贪⼼算法适⽤类型通⽤问题优化问题优化问题⼦问题结构每个⼦问题不同很多⼦问题重复(不独⽴)只有⼀个⼦问题最优⼦结构不需要必须满⾜必须满⾜⼦问题数全部⼦问题都要解决全部⼦问题都要解决只要解决⼀个⼦问题⼦问题在最优解⾥全部部分部分选择与求解次序先选择后解决⼦问题先解决⼦问题后选择先选择后解决⼦问题分治算法特征:1)规模如果很⼩,则很容易解决。
//⼀般问题都能满⾜2)⼤问题可以分为若⼲规模⼩的相同问题。
//前提3)利⽤⼦问题的解,可以合并成该问题的解。
//关键4)分解出的各个⼦问题相互独⽴,⼦问题不再包含公共⼦问题。
//效率⾼低【⼀】动态规划:依赖:依赖于有待做出的最优选择实质:就是分治思想和解决冗余。
⾃底向上(每⼀步,根据策略得到⼀个更⼩规模的问题。
最后解决最⼩规模的问题。
得到整个问题最优解)特征:动态规划任何⼀个i+1阶段都仅仅依赖 i 阶段做出的选择。
⽽与i之前的选择⽆关。
但是动态规划不仅求出了当前状态最优值,⽽且同时求出了到中间状态的最优值。
缺点:空间需求⼤。
【⼆】贪⼼算法:依赖:依赖于当前已经做出的所有选择。
⾃顶向下(就是每⼀步,根据策略得到⼀个当前最优解。
传递到下⼀步,从⽽保证每⼀步都是选择当前最优的。
最后得到结果)【三】分治算法:实质:递归求解缺点:如果⼦问题不独⽴,需要重复求公共⼦问题---------------------------------------------------------------------------------------------------------------------------贪⼼算法:贪⼼算法采⽤的是逐步构造最优解的⽅法。
递归和分治法
递归和分治法摘要:一、递归与分治法的概念1.递归:函数调用自身的思想2.分治法:把一个大问题分解成若干个小问题二、递归与分治法的联系与区别1.递归通常作为分治法的实现方式2.分治法不一定要用递归实现三、递归与分治法的应用实例1.快速排序算法2.归并排序算法3.汉诺塔问题正文:递归和分治法是两种在计算机科学中经常使用的解决问题的方法。
递归是一种函数调用自身的思想,即函数在执行过程中,会调用自身来完成某些操作。
而分治法则是把一个大问题分解成若干个小问题,然后逐个解决这些小问题,最后再把它们的解合并,得到大问题的解。
这两种方法在某些情况下可以相互转化,递归通常作为分治法的实现方式,但分治法不一定要用递归实现。
递归与分治法之间的联系在于,递归通常是分治法的实现方式。
在分治法中,我们会把一个大问题分解成若干个小问题,然后通过递归的方式,逐个解决这些小问题。
最后,再把它们的解合并,得到大问题的解。
在这个过程中,递归函数的调用栈会随着问题规模的减小而减小,最终回到原点,从而完成问题的求解。
然而,分治法并不一定要用递归实现。
在一些情况下,我们可以通过迭代的方式,逐个解决小问题,然后把它们的解合并。
这种方式虽然不是通过递归函数调用自身来实现的,但它仍然符合分治法的思想,即把大问题分解成小问题,逐个解决。
递归和分治法在实际问题中有很多应用。
例如,快速排序算法和归并排序算法都是基于分治法的思想设计的。
在快速排序算法中,我们选择一个基准元素,然后把数组中小于基准的元素放在左边,大于基准的元素放在右边,再对左右两个子数组递归地执行相同的操作,直到数组有序。
而在归并排序算法中,我们同样把数组分成左右两个子数组,然后递归地对它们进行排序,最后再把排序好的子数组合并成一个有序的数组。
另一个例子是汉诺塔问题。
在这个问题中,有三个柱子和一个大小不同的圆盘。
要求把圆盘从第一个柱子移动到第三个柱子,每次只能移动一个圆盘,并且大盘不能放在小盘上。
递归与分治算法
递归与分治算法
递归和分治算法是计算机科学中两种常见的算法设计技术。
递归是一种直接或间接调用自身函数或者方法的算法。
在递归算法中,函数在其定义中使用了函数自身的调用。
递归算法通常用于解决需要重复执行相同任务的问题,例如遍历树结构、递归搜索等。
递归算法的优点是代码简洁、易于理解,但需要注意递归深度的限制以及可能引发栈溢出的问题。
分治算法是一种将问题分解为多个子问题,并分别解决子问题的算法。
分治算法通过将大问题分解为小问题,并将小问题的解合并成大问题的解来解决问题。
分治算法通常用于排序、查找、矩阵乘法等问题。
分治算法的优点是可以将复杂问题分解为简单问题,降低问题的复杂度,但需要注意分解的子问题必须是相互独立的。
在实际应用中,递归和分治算法通常结合使用。
例如,快速排序算法就是一种典型的分治算法,它通过选择一个基准元素,将数组分为两个子数组,并对每个子数组递归地进行排序,最终合并两个有序子数组得到排序后的数组。
总之,递归和分治算法是计算机科学中重要的算法设计技术,它们可以有效地解决许多复杂的问题。
在实际应用中,需要根据问题的特点选择合适的算法,并注意算法的时间复杂度和空间复杂度。
启发式规则,分治法,递归,汉诺塔,排序算法
4.3 排序问题中的分治法
4.3.1 4.3.2 归并排序 快速排序
4.3.1 归并排序
二路归并排序的分治策略是: (1)划分:将待排序序列r1, r2, …, rn划分为两个 长度相等的子序列r1, …, rn/2和rn/2+1, …, rn; (2)求解子问题:分别对这两个子序列进行排 序,得到两个有序子序列;
二路归并排序的合并步的时间复杂性为O(n), 所以,二路归并排序算法存在如下递推式:
1 T (n) = 2T ( n 2 ) + n
n =1 n >1
根据1.2.4节的主定理,二路归并排序的时间代价是 O(nlog2n)。 二路归并排序在合并过程中需要与原始记录序列同 样数量的存储空间,因此其空间复杂性为O(n)。
第4章 分治法
4.1 概 述
4.2 递 归 4.3 排序问题中的分治法 4.4 组合问题中的分治法 4.5 几何问题中的分治法
4.1 概 述
4.1.1 分治法的设计思想 4.1.2 分治法的求解过程
4.1.1 分治法的设计思想
将一个难以直接解决的大问题,划分成一些规模较小的
子问题,以便各个击破,分而治之。更一般地说,将要求解
4.2 递 归
4.2.1 递归的定义
4.2.2 递归函数的运行轨迹
4.2.3 递归函数的内部执行过程
4.2.1 递归的定义
递归(Recursion)就是子程序(或函数)直 接调用自己或通过一系列调用语句间接调用自己, 是一种描述问题和解决问题的基本方法。 递归有两个基本要素: ⑴ 边界条件:确定递归到何时终止; ⑵ 递归模式:大问题是如何分解为小问题的。
分治法的典型情况
原问题 的规模是n
子问题1 的规模是n/2
递归和分治区别
递归和分治区别分治法的基本思想:将⼀个规模为n的问题分解为k个规模较⼩的⼦问题,这些⼦问题互相独⽴且与原问题相同。
递归地解这些问题,然后将各个⼦问题的解合并成原问题的解。
分治法所能解决的问题⼀般具有以下⼏个特征:该问题的规模缩⼩到⼀定的程度就可以容易地解决;因为问题的计算复杂性⼀般是随着问题规模的增加⽽增加,因此⼤部分问题满⾜这个特征。
该问题可以分解为若⼲个规模较⼩的相同问题,即该问题具有最优⼦结构性质这条特征是应⽤分治法的前提,它也是⼤多数问题可以满⾜的,此特征反映了递归思想的应⽤利⽤该问题分解出的⼦问题的解可以合并为该问题的解;能否利⽤分治法完全取决于问题是否具有这条特征,如果具备了前两条特征,⽽不具备第三条特征,则可以考虑贪⼼算法或动态规划。
该问题所分解出的各个⼦问题是相互独⽴的,即⼦问题之间不包含公共的⼦问题。
这条特征涉及到分治法的效率,如果各⼦问题是不独⽴的,则分治法要做许多不必要的⼯作,重复地解公共的⼦问题,此时虽然也可⽤分治法,但⼀般⽤动态规划较好(例如记忆化搜索是分治转化为动归的⼀个经典, 要注意)。
分治法的复杂性分析:⼀个分治法将规模为n的问题分成k个规模为n/m的⼦问题去解时间复杂度多为O(n)递归的优点:结构清晰,可读性强,⽽且容易⽤数学归纳法来证明算法的正确性,因此它为设计算法、调试程序带来很⼤⽅便。
缺点:递归算法的运⾏效率较低,⽆论是耗费的计算时间还是占⽤的存储空间都⽐⾮递归算法要多。
解决⽅法:在递归算法中消除递归调⽤,使其转化为⾮递归算法。
采⽤⼀个⽤户定义的栈来模拟系统的递归调⽤⼯作栈。
该⽅法通⽤性强,但本质上还是递归,只不过⼈⼯做了本来由编译器做的事情,优化效果不明显。
⽤递推来实现递归函数。
通过变换能将⼀些递归转化为尾递归(尾递归是极其重要的,不⽤尾递归,函数的堆栈耗⽤难以估量,需要保存很多中间函数的堆栈。
⽐如f(n, sum) = f(n-1) + value(n) + sum; 会保存n个函数调⽤堆栈,⽽使⽤尾递归f(n, sum) = f(n-1, sum+value(n)); 这样则只保留后⼀个函数堆栈即可,之前的可优化删去。
汉诺塔解法原理
汉诺塔解法原理汉诺塔是一道经典的递归问题。
要解决汉诺塔问题,我们需要了解一些递归和分治的基本原理。
汉诺塔问题描述汉诺塔问题是指在一根柱子上按大小顺序放置 N 个盘子,大盘子在下面,小盘子在上面。
现在要求将这些盘子全部移到另一个柱子上,可以借助中间的柱子,但是要满足在移动的过程中始终保持大盘子在下、小盘子在上的原则。
汉诺塔解法汉诺塔问题可以用递归算法求解。
具体解法分为三个步骤:1. 将 n-1 个盘子从 A 移动到 B(借助 C)2. 将第 n 个盘子从 A 移动到 C3. 将 n-1 个盘子从 B 移动到 C(借助 A)其中,第 1 步和第 3 步是递归步骤,第 2 步是基础步骤。
在第 1 步和第 3 步中,我们需要先将 n-1 个盘子从 A 移动到 B(或从 B 移动到A),这是通过递归调用将问题规模缩小实现的。
当问题规模足够小时,基础步骤中进行盘子移动的操作就可以解决问题。
递归基本原理递归算法是一种非常高效的算法,可以解决许多问题。
在使用递归算法时,我们需要注意以下几点:1. 递归函数必须有一个基准条件,这个条件用于判断递归何时停止;2. 递归函数必须能够缩小问题规模,这样才能使得递归过程终止;3. 递归函数必须能够不断地将问题分解为同样的形式,这样才能简化递归算法的实现。
1. 分治算法必须要有一个基础步骤,这个步骤可以解决问题的一部分;2. 分治算法必须能够将问题分为若干个子问题,这些子问题与原问题形式相同;3. 子问题必须能够递归地求解。
总结汉诺塔问题是一道经典的递归问题,可以用递归算法求解。
递归算法的基本原理是基准条件、问题规模缩小和问题形式简化。
重点在递归的时候能够将问题不断缩小,同时保证在基础步骤中能够解决问题的一部分。
分治算法与递归类似,也是一种高效的算法。
分治算法的基本原理是基础步骤、问题分解和递归求解。
分治算法能够将问题分解成若干个子问题,这些子问题与原问题形式相同,这样就能够简化算法实现。
算法设计与分析实验报告
本科实验报告课程名称:算法设计与分析实验项目:递归与分治算法实验地点:计算机系实验楼110专业班级:物联网1601 学号:2016002105 学生姓名:俞梦真指导教师:郝晓丽2018年05月04 日实验一递归与分治算法1.1 实验目的与要求1.进一步熟悉C/C++语言的集成开发环境;2.通过本实验加深对递归与分治策略的理解和运用。
1.2 实验课时2学时1.3 实验原理分治(Divide-and-Conquer)的思想:一个规模为n的复杂问题的求解,可以划分成若干个规模小于n的子问题,再将子问题的解合并成原问题的解。
需要注意的是,分治法使用递归的思想。
划分后的每一个子问题与原问题的性质相同,可用相同的求解方法。
最后,当子问题规模足够小时,可以直接求解,然后逆求原问题的解。
1.4 实验题目1.上机题目:格雷码构造问题Gray码是一个长度为2n的序列。
序列无相同元素,每个元素都是长度为n的串,相邻元素恰好只有一位不同。
试设计一个算法对任意n构造相应的Gray码(分治、减治、变治皆可)。
对于给定的正整数n,格雷码为满足如下条件的一个编码序列。
(1)序列由2n个编码组成,每个编码都是长度为n的二进制位串。
(2)序列中无相同的编码。
(3)序列中位置相邻的两个编码恰有一位不同。
2.设计思想:根据格雷码的性质,找到他的规律,可发现,1位是0 1。
两位是00 01 11 10。
三位是000 001 011010 110 111 101 100。
n位是前n-1位的2倍个。
N-1个位前面加0,N-2为倒转再前面再加1。
3.代码设计:}}}int main(){int n;while(cin>>n){get_grad(n);for(int i=0;i<My_grad.size();i++)cout<<My_grad[i]<<endl;My_grad.clear();}return 0;}运行结果:1.5 思考题(1)递归的关键问题在哪里?答:1.递归式,就是如何将原问题划分成子问题。
五大常用算法简介
五⼤常⽤算法简介1、递归与分治递归算法:直接或者间接不断反复调⽤⾃⾝来达到解决问题的⽅法。
这就要求原始问题可以分解成相同问题的⼦问题。
⽰例:阶乘、斐波纳契数列、汉诺塔问题斐波纳契数列:⼜称黄⾦分割数列,指的是这样⼀个数列:1、1、2、3、5、8、13、21、……在数学上,斐波纳契数列以如下被以递归的⽅法定义:F1=1,F2=1,Fn=F(n-1)+F(n-2)(n>2,n∈N*))。
分治算法:待解决复杂的问题能够简化为⼏个若⼲个⼩规模相同的问题,然后逐步划分,达到易于解决的程度。
1、将原问题分解为n个规模较⼩的⼦问题,各⼦问题间独⽴存在,并且与原问题形式相同2、递归的解决各个⼦问题3、将各个⼦问题的解合并得到原问题的解⽰例:棋盘覆盖、找出伪币、求最值棋盘覆盖:在⼀个(2k)*(2k)个⽅格组成的棋盘上,有⼀个特殊⽅格与其他⽅格不同,称为特殊⽅格,称这样的棋盘为⼀个特殊棋盘。
要求对棋盘的其余部分⽤L型⽅块填满2、动态规划动态规划与分治法相似,都是组合⼦问题的解来解决原问题的解,与分治法的不同在于:分治法的⼦问题是相互独⽴存在的,⽽动态规划应⽤于⼦问题重叠的情况。
动态规划⽅法通常⽤来求解最优化问题,这类问题可以有很多可⾏解,每个解都有⼀个值,找到具有最优值的解称为问题的⼀个最优解,⽽不是最优解,可能有多个解都达到最优值。
设计动态规划算法的步骤:1、刻画⼀个最优解的结构特征2、递归地定义最优解的值3、计算最优解的值,通常采⽤⾃底向上的⽅法4、利⽤算出的信息构造⼀个最优解⽰例:0-1背包问题,钢条切割问题等。
3、贪⼼算法贪⼼算法是就问题⽽⾔,选择当下最好的选择,⽽不从整体最优考虑,通过局部最优希望导致全局最优。
贪⼼算法的要素1)贪⼼选择性质:可以通过局部最优选择来构造全局最优解。
换⾔之,直接做出在当前问题中看来最优的选择,⽽不必考虑⼦问题的解。
2)最优⼦结构:⼀个问题的最优解包含其⼦问题的最优解。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2013-7-8
20
递归小结
优点:结构清晰,可读性强,而且容易用数学归 纳法来证明算法的正确性,因此它为设计算法、 调试程序带来很大方便。 缺点:递归算法的运行效率较低,无论是耗费的 计算时间还是占用的存储空间都比非递归算法 要多。
2013-7-8
21
递归小结
解决方法:在递归算法中消除递归调用,使其转 化为非递归算法。 1.采用一个用户定义的栈来模拟系统的递归调用 工作栈。该方法通用性强,但本质上还是递归, 只不过人工做了本来由编译器做的事情,优化 效果不明显。 2.用递推来实现递归函数。 3.通过Cooper变换、反演变换能将一些递归转化 为尾递归,从而迭代求出结果。
2013-7-8
边界条件
递归方程
8
A(1,0) 2 A(0, m) 1 m0 A(n,0) n 2 n2 A(n, m) A( A(n 1, m), m 1) n, m 1
2013-7-8 9
2.1
递归的概念
例3 Ackerman函数 当一个函数及它的一个变量是由函数自身定义时,称这 个函数是双递归函数。 Ackerman函数A(n,m)定义如下:
分治法的设计思想是,将一个难以直接解决的大问题, n = T(n) 分割成一些规模较小的相同问题,以便各个击破, 分而治之。 凡治众如治寡,分数是也。 n/2 n/2 n/2 ----孙子兵法 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
后两种方法在时空复杂度上均有较大改善, 但其适用范围有限。
2013-7-8 2具有以下几个特征: • 该问题的规模缩小到一定的程度就可以容易地解决; • 该问题可以分解为若干个规模较小的相同问题,即该 问题具有最优子结构性质 • 利用该问题分解出的子问题的解可以合并为该问题的 解; • 该问题所分解出的各个子问题是相互独立的,即子问 题之间不包含公共的子问题。 这条特征涉及到分治法的效率,如果各子问题是不 能否利用分治法完全取决于问题是否具有这条特征, 这条特征是应用分治法的前提,它也是大多数问题 因为问题的计算复杂性一般是随着问题规模的增加 可以满足的,此特征反映了递归思想的应用 而增加,因此大部分问题满足这个特征。 独立的,则分治法要做许多不必要的工作,重复地 如果具备了前两条特征,而不具备第三条特征,则 可以考虑贪心算法或动态规划。 解公共的子问题,此时虽然也可用分治法,但一般 用动态规划较好。
下面来看几个实例。
2013-7-8 6
2.1
递归的概念
边界条件
例1 阶乘函数 阶乘函数可递归地定义为:
n0 1 n! n(n 1)! n 0
递归方程 边界条件与递归方程是递归函数的二个要素,递归函 数只有具备了这两个要素,才能在有限次计算后得出 结果。
2013-7-8 7
2.1
T(n)
n/2
=
n/2
n
n/2 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
2013-7-8 4
算法总体思想
• 将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
2013-7-8
14
2.1
递归的概念
例5 整数划分问题 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1。 正整数n的这种表示称为正整数n的划分。求正整数n的不 同划分个数。 例如正整数6有如下11种不同的划分: 6; 5+1; 4+2,4+1+1; 3+3,3+2+1,3+1+1+1; 2+2+2,2+2+1+1,2+1+1+1+1; 1+1+1+1+1+1。
2013-7-8
19
2.1
递归的概念
例6 Hanoi塔问题 public static void hanoi(int n, int a, int b, int c) 当n=1时,问题比较简单。此时,只要将编号为1的圆盘从塔座a直 在问题规模较大时,较难找到一般的方法,因此我们尝试 接移至塔座b上即可。 用递归技术来解决这个问题。 { 思考题:如果塔的个数变为a,b,c,d 当n>1时,需要利用塔座c作为辅助塔座。此时若能设法将n-1个 if (n > 0) 四个,现要将n个圆盘从a全部移动 较小的圆盘依照移动规则从塔座a移至塔座c,然后,将剩下的最 { 到d,移动规则不变,求移动步数最 大圆盘从塔座a移至塔座b,最后,再设法将n-1个较小的圆盘依照 hanoi(n-1, a, c, b); 小的方案。 移动规则从塔座c移至塔座b。 move(a,b); 由此可见,n个圆盘的移动问题可分为2次n-1个圆盘的移动问题, hanoi(n-1, c, b, a); 这又可以递归地用上述方法来做。由此可以设计出解Hanoi塔问题 的递归算法如下。 } }
T(n/2)
T(n/2)
2
算法总体思想
• 将求出的小规模的问题的解合并为一个更大规模的问 • 对这k个子问题分别求解。如果子问题的规模仍然不够 题的解,自底向上逐步求出原来问题的解。 小,则再划分为k个子问题,如此递归的进行下去,直 到问题规模足够小,很容易求出其解为止。
T(n)
n/2
=
n/2
n
n/2 n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4
2013-7-8 3
算法总体思想
• 将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
n! 1 2 3 (n 1) n
1 5 n1 1 5 n1 1 F (n) 2 5 2
但本例中的Ackerman函数却无法找到非递归的定义。
11
2013-7-8
2.1
A(1,0) 2 A(0, m) 1 m0 A(n,0) n 2 n2 A(n, m) A( A(n 1, m), m 1) n, m 1
2013-7-8 10
2.1
递归的概念
例3 Ackerman函数 前2例中的函数都可以找到相应的非递归方式定义:
2013-7-8 15
2.1
递归的概念
例5 整数划分问题 前面的几个例子中,问题本身都具有比较明显的递归关系,因 而容易用递归函数直接求解。 在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关 系,因此考虑增加一个自变量:将最大加数n1不大于m的划分个 数记作q(n,m)。可以建立q(n,m)的如下递归关系。
2013-7-8 5
2.1
递归的概念
• 直接或间接地调用自身的算法称为递归算法。 用函数自身给出定义的函数称为递归函数。 • 由分治法产生的子问题往往是原问题的较小模 式,这就为使用递归技术提供了方便。在这种 情况下,反复应用分治手段,可以使子问题与 原问题类型一致而其规模却不断缩小,最终使 子问题缩小到很容易直接求出其解。这自然导 致递归过程的产生。 • 分治与递归像一对孪生兄弟,经常同时应用在 算法设计之中,并由此产生许多高效算法。
递归的概念
例2 Fibonacci数列 无穷数列1,1,2,3,5,8,13,21,34,55,…,被 称为Fibonacci数列。它可以递归地定义为:
1 n0 F ( n) 1 n 1 F (n 1) F (n 2) n 1
第n个Fibonacci数可递归地计算如下: public static int fibonacci(int n) { if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2); }
例6 Hanoi塔问题 设a,b,c是3个塔座。开始时,在塔座a上有一叠共n个圆 盘,这些圆盘自下而上,由大到小地叠在一起。各圆 盘从小到大编号为1,2,…,n,现要求将塔座a上的这一 叠圆盘移到塔座b上,并仍按同样顺序叠臵。在移动圆 盘时应遵守以下移动规则: 规则1:每次只能移动1个圆盘; 规则2:任何时刻都不允许将较大的圆盘压在较小的圆盘 之上; 规则3:在满足移动规则1和2的前提下,可将圆盘移至 a,b,c中任一塔座上。
(1) q(n,1)=1,n1; (3) q(n,n)=1+q(n,n-1); 当最大加数n1不大于1时,任何正整数n只有一种划分形式, 正整数n的划分由n1=n的划分和n1≤n-1的划分组成。 n 即 n 111 (2) q(n,m)=q(n,n),mn; (4) q(n,m)=q(n,m-1)+q(n-m,m),n>m>1; 正整数n的最大加数n1不大于m的划分由n1=m的划分和 最大加数n1实际上不能大于n。因此,q(1,m)=1。 n1≤n-1 的划分组成。
2013-7-8 16
2.1
递归的概念
例5 整数划分问题 前面的几个例子中,问题本身都具有比较明显的递归关系,因 而容易用递归函数直接求解。 在本例中,如果设p(n)为正整数n的划分数,则难以找到递归关 系,因此考虑增加一个自变量:将最大加数n1不大于m的划分个 数记作q(n,m)。可以建立q(n,m)的如下递归关系。