2020蓝桥杯备战-第七章- 数递归、DFS、剪枝、回溯-数值型递归

题目:

  1. 上楼梯
  2. 斐波那契数列
  3. 机器人走方格
  4. 硬币表示

1.上楼梯

题目描述:

有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶、3阶。 请实现一个方法,计算小孩有多少种上楼的方式。
为了防止溢出,请将结果Mod 1000000007
给定一个正整数int n,请返回一个数,代表上楼的方式数。
保证n小于等于100000。

首先有两种方法:
  1. 递归
  2. 迭代
(1)递归
分析:

首先,递归比较耗时,耗时的原因是递归不断地在调用栈,还有就是重复的运算比较多。37次已经不能秒杀了,递归的基本思想就是数学归纳。

下面先从小向大开始排列。
n为楼梯的阶数,k为上楼梯的方法种类数

n0123456n
k112471324前三位数字之和

此时我们发现上楼梯方法种类数是前三个数字之和。如果用递归来解决,也就是说需要逆向思考,我们上楼梯,不妨把它回放一下。从第n(n>6)个台阶开始往下退,因为一次只能下1或2或3个台阶,因此我们就有了从这样几种方法,从第n-1,n-2,n-3个台阶上到第n个台阶,那么n-1可以分为n-2,n-3,n-4这三种,n-2可以分为n-3,n-4,n-5这三种,n-3可以分为n-4,n-5,n-6这几种情况。一次这样分解下去,其实就是一颗完全三叉树的形式。直到树最下面的台阶为1或2或3时,就把所有的分支加起来就可以计算n的台阶数了。

递归三要素:
  1. 变量与不变量
  2. 递归退出的条件
  3. 递归表达式
    代码如下()
//上楼梯-递归(当n为37左右需要等待很长时间,不能秒杀了,迭代可以)
	public static final int mod=1000007;
	static int stairs(int n)
	{
		if(n==0 || n==1) return 1;
		if(n==2) return 2;
		if(n==3) return 4;
		return stairs(n-1)%mod+stairs(n-2)%mod+stairs(n-3)%mod;
	}
(2)迭代

分析:也就是在循环里面,不断地改变那个k-1和k-2的值,让他循环加起来,得到k。
这样做时间是比较快的,37次秒杀。
代码如下:

//上楼梯-迭代
	static int stairs_for(int n)
	{
		int x1=1;
		int x2=1;
		int x3=2;
		int temp;
		//x4=x1+x2+x3
		//x5+x2+x3+x4
		//xn=x(n-3)+x(n-2)+x(n-1);
		for(int i=4;i<=n;i++)
		{
			temp=x1%mod;
			x1=x2%mod;
			x2=x3%mod;
			x3=(temp+(x1+x2)%mod)%mod;
		}
		return x3;
	}

2.斐波那契数列,类似题目

代码如下:

求第n项的递归形式
	//斐波那契-递归(当n为45左右就需要很长时间了,不可秒杀,迭代可以)
	static int fib(int n)
	{
		if(n==0 || n==1) return 1;
		if(n==2) return 1;
		return fib(n-1)+fib(n-2);
	}
求第n项的迭代形式
//斐波那契数列求第n项-迭代
	static int fib_for(int n)
	{
		int x1=1;
		int x2=1;
		int temp;
		for(int i=3;i<=n;i++)
		{
			temp=x1;
			x1=x2;
			x2=temp+x1;
		}
		return x2;
	}
求前n项和
//斐波那契数列求和-迭代
	static int fib_sum(int n)
	{
		int x1=1;
		int x2=1;
		int temp;
		int sum=1;
		//x4=x1+x2+x3
		//x5+x2+x3+x4
		//xn=x(n-3)+x(n-2)+x(n-1);
		for(int i=2;i<=n;i++)
		{
			sum=sum+x2;
			temp=x1;
			x1=x2;
			x2=temp+x1;
		}
		return sum;
	}

3.机器人走方格

题目描述:

有一个XxY的网格,一个机器人只能走格点且只能向右或向下走,要从左上角走到右下角。 请设计一个算法,计算机器人有多少种走法。
给定两个正整数int x,int y,请返回机器人的走法数目。
保证x+y小于等于12。

分析:

这道题和上面的有所不同,因为这涉及到二维的变化。首先,现列举1x1 1x2 2x1 2x2 2x3 3x2的情况,基本就可以得到3x3的答案了。

代码如下:

求第n项的递归形式
//机器人走方格-递归
	static int robot(int x,int y)
	{
		if(x==1||y==1)return 1;
		return robot(x,y-1)+robot(x-1,y);
	}
求第n项的迭代形式
//机器人走方格-迭代
	static int robot_for(int m,int n)
	{
		int [][] a=new int [m+1][n+1];
		for(int j=0;j<n;j++)
			a[0][j]=1;
		for(int i=0;i<m;i++)
			a[i][0]=1;
		for(int i=1;i<m;i++)
		{
			for(int j=1;j<n;j++)
			{
				a[i][j]=a[i-1][j]+a[i][j-1];
			}
		}
		return a[m-1][n-1];

4.硬币表示

题目描述:

假设我们有8种不同面值的硬币{1,2,5,10,20,50,100,200},用这些硬币组合够成一个给定的数值n。 例如n=200,那么一种可能的组合方式为 200 = 3 1 + 1*2 + 1*5 + 2*20 + 1 50 + 1 * 100. 问总共有多少种可能的组合方式?

分析:

这道题比上面的变得又复杂了,但是万变不离其宗,只要找到其递归的变量与不变量,递归退出条件和递归表达式,就能够写出来。首先,输入值为n面值为1,5,10,25,按照递归的形式去测试一下,我们直观上的应该是从小王大找规律,而递归就是我们的你想表达的结晶。那我们直接从逆向思考,可见变量之一定是这个n,其次就是这个面值的变化,但是面值的变化是固定而有序的,那我们就把这个面值放在数组中,我们让下标递减,这样,我们就发现下标对应的面值的变化也是从25-10-5-1,到1时应该就是递归的出口了。还有一个重要的变量,就是每一个面值所需要的数量。这个数量跟n有关还跟已经使用面值和这个面值的数量有关,他还决定着最大面值的最大数量。

举例:

假设:给定数值为10分

10分面值的有0或者1个10分的,当有0个时,可以分给5分面值的,此时5分的可以有0,1,2个,0个时都用1分面值表示,1个时用5个1分表示,2个时不用1分表示。这样也就是四条路径。如果每个小圈有权值的话,每一支路径的和就都等于10,共有4条。
代码如下
//硬币表示
	static int coin(int n,int value[],int cur)
	{
		int sum=0;//记录总数
		if(cur==0) return 1;//当只用1分的面值时,也就是递归出口
		//循环递归,也就是多分递归(例如机器人走方格时二分递归,每次有两条路径可走,这里就有不确定条路可走(重要因素:最大面值的使用数量))
		for(int i=0;i*value[cur]<=n;i++)//从大面值的往小面值递归。
			//剩余的分 放到下面继续递归也就是   n-i*value[cur]
			sum+=coin(n-i*value[cur],value,cur-1);//返回值是最小的,最后累加到sum中
		return sum;
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您解答关于回溯法求解n皇后问题的问题。 首先,回溯法是一种通过探索所有可能的候选解来找出所有的解的算法。如果候选解被确认不是一个解的话(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化把这些不合适的候选解排除掉。 在n皇后问题中,我们要在一个n x n的棋盘上放置n个皇后,使得每一行、每一列以及对角线上都只有一个皇后。为了解决这个问题,我们可以使用回溯算法。 回溯算法中,我们需要定义一个剪枝,用于判断当前的候选解是否是可行解。对于n皇后问题,剪枝可以通过以下方式实现: 1. 判断当前的皇后是否与之前的皇后在同一列上,如果是,则返回False。 2. 判断当前的皇后是否与之前的皇后在同一对角线上,如果是,则返回False。 3. 如果当前的皇后与之前的皇后都不在同一列和同一对角线上,则返回True。 在n=3时,搜索空间如下(其中字表示皇后所在的列): ``` 1 2 3 ------- 1|X . .| ------- 2|. . X| ------- 3|. X .| ------- ``` 在n=4时,搜索空间如下: ``` 1 2 3 4 --------- 1|X . . .| --------- 2|. . X .| --------- 3|. . . X| --------- 4|. X . .| --------- ``` 可以看到,随着n的增加,搜索空间指级增长,因此n皇后问题的时间复杂度为O(n!),在n较大时会变得非常耗时。因此,在实际问题中,需要使用一些优化技巧来减小搜索空间和提高算法效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值