【算法】递推、分治、递归(P.S.汉诺塔无敌)

转载来源:https://blog.csdn.net/summer_dew/article/details/82078565?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522160082235719195162137781%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=160082235719195162137781&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-2-82078565.first_rank_v2_rank_v25&utm_term=%E5%88%86%E6%B2%BB%E6%B3%95%E9%80%92%E6%8E%A8%E5%85%AC%E5%BC%8F&spm=1018.2118.3001.4187

感谢分享@GeoDoer!!!

 

文章目录


在这里插入图片描述

 

1. 递归与分治法的区别

1.1 递归

从上往下的分析,然后回溯:从n的情况一直往下走->走到1(特殊情况)->然后往回计算->最终得到n的情况

必须满足:

  1. 在每一次调用自己时,必须是在某种意义上更接近于解(每次操作是收敛的):问题规模越来越小
  2. 必须有一次终止处理或计算的准则:必须要有一个出口

1.2 分治法

利用分治法求解,所得子问题的类型常常和原问题相同,因而很自然地使用递归求解

1.2.1 思路

  1. 输入【规模为n】的函数或问题
  2. 用某种方法把输入【分割成k(1<k≤n)个子集】,从而【产生l个子问题】
  3. 再用某种方法把它们【组合成原来问题的解】

1.3 区别

  1. 递归:是一种算法结构
  2. 分割求解:是一种算法设计思想

2 递归

2.1 什么情况下用

  1. 用分割求解设计算法时,子问题和原问题的性质相同
  2. 问题的当前一步解决之后,余下的问题和原问题性质相同,则自然导致递归求解

2.2 怎么写

  1. 把大问题,分成几个小问题
  2. 找到一个特殊情况,那个特殊情况的解是确定的->这个特殊情况就是【基本项】
  3. 思考每次相同的参数有哪些,将它们写成函数参数->整理出统一形式,即【归纳项】

从上面可以知道,我们需要确定两个东西:

  1. 基本项:描述一个或几个递归过程的终结状态
    【终结状态】出口,特殊情况
  2. 归纳项:实现从当前状态到终结状态的转化
    参数对好了:原问题的参数、子问题的参数要对好

2.3 特点

  1. 可读性好,但也不要单纯追求形式
  2. 递归<->利用栈实现的非递归函数(两者可以相互实现)
  3. 递归函数递归层次的深度决定【所需存储量的大小】

2.4 例题

  1. 排列组合
  2. 按顺序入栈的所有可能

3 递归树

分析递归算的工具【递归树】,通过递归树我们可以很清楚的分析递归

例如:

  1. 递归树的【深度】=递归函数的【递归深度】,而递归深度决定【存储量的大小】
  2. 递归树上的【结点数目】=函数中的主要【操作重复进行的次数】

3.1 举例

汉诺塔问题

// 将n个盘子从x借助y移动到z
// 例如:move(3,'A','B','Z') 将3个盘子从'A'借助'B'移动到'Z'
void move(int n,char x,char y,char z) {
	if (1==n) //只剩下一个盘子
		printf("%c-->%c",x,z); //直接从x->z
	else {
		move(n-1,x,z,y);	//将n-1个盘子从x借助z移动到y
		printf("%c-->%c",x,z);
		move(n-1,y,x,z); //将n-1个盘子从y借助x移动到z
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这里写图片描述

通过【递归树】很容易发现:

  1. 结点数=移动个数
  2. 中序序列=圆盘移动操作的序列
  3. 性能:
    • 设执行时间为T(n)
    • 递归方程为T(n)=2T(n-1)+C
    • 初始条件为T(0)=0

3.2 递归怎么分析好不好

以下情况表明【递归函数不适用】该问题

3.2.1 递归树锐化为单支树

【问题】求解:n!

【n!的递归树】
这里写图片描述

【分析】

  1. 直线返回
  2. 递归深度很深,占的存储空间很大

3.2.2 递归树中含有很多相同的结点

【问题】斐波那契数列
F[n]=F[n-1]+F[n-2](n>=2,F[0]=0,F[1]=1)

【递归树】
这里写图片描述

【分析】

  1. 相同结点很多,不适合用递归
  2. 这个用递推,从下往上,会容易点

4 递归与递推

  1. 递归:从上往下,走到最下,再回溯回去,在回溯的过程中计算
  2. 递推:从下而上,在最下面,计算出最简单的,往上走

【举例】斐波那契数列
F[n]=F[n-1]+F[n-2](n>=2,F[0]=0,F[1]=1)

【计算顺序】

F[0]=0,F[1]=1 -> F[2]=F[0]+F[1] -> F[3] -> F[4] -> …

从特殊情况(下)往上递推,每计算一个,就把结果存下来,再往上走

5 递归应用

5.1 斐波那契数列

又名: 兔子数列 黄金分割数列

  1. 递推公式
F(0)=1
F(1)=1
F(n)=F(n-1)+F(n-2)
  • 1
  • 2
  • 3
  1. 通项公式

当n趋向于无穷大时,前一项与后一项的比值越来越逼近黄金分割0.618

5.2 杨辉三角

它把二次项系数图形化,把组合数内在的一些代数性质直观地从图形中体现出来。

5.2.1 性质

前提:每行端点与结尾的数为1

基础性质:

  1. 每行数字左右对称,由1开始逐渐变大
  2. 第n行的数字有n项
  3. 第n行数字和为2^(n-1)
  4. 第n行的m个数可表示为C(n-1,m-1)
  5. 第n行的第m个数和第n-m+1个数相等,即组合数性质之一
  6. C(n+1,i)=C(n,i)+C(n,i-1):每个数等于它上方两数之和

不常用的性质:
5. (a+b)^n的展开式中的各项系数依次对应杨辉三角的第(n+1)行中的每一项
6. 将第2n+1行第1个数,跟第2n+2行第3个数、第2n+3行第5个数……连成一线,这些数的和是第4n+1个斐波那契数;将第2n行第2个数(n>1),跟第2n-1行第4个数、第2n-2行第6个数……这些数之和是第4n-2个斐波那契数

5.3 汉诺塔

又名,河内塔

有三根相邻的柱子,标号为A,B,C
A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘
要把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方
请问至少需要多少次移动,设移动次数为H(n)

5.4 八皇后问题

8x8格国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行,同一列,同一斜线上,有多少种摆法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值