⚡️前言⚡️
本篇文章是针对acwing上的蓝桥杯课程所做的总结,有对应习题与练习,本篇文章主要针对递归常见的模型及对应例题的总结,算法的摩西其实不多,希望能与与大家共同学习,备战蓝桥!
🍉博客主页: 🍁【如风暖阳】🍁
🍉精品Java专栏【Javase】、【Java数据结构】、【备战蓝桥】
🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉
🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)
《备战蓝桥》之递归
📍内容导读📍
🍅知识总结
在蓝桥杯历年真题中,递归与递推考点出现的次数较为高频,最为常见的递归便是斐波那契数列,下边就针对斐波那契数列来总结一下这一类题的做题方法。
我们知道形容1,2,3,5,8,13……这样,后一项等于前两项和的数列就称作斐波那契数列,而这种递归问题都可以抽象出一颗递归搜索树,我们通过递归搜索树这种形象的展示,就可以对递归或递推问题有一定的把握。
我们以求斐波那契数列第六项为例:
public static int fab(int n) {
if(n==1) {
return 1;
}else if(n==2) {
return 2;
}else
return fab(n-1)+fab(n-2);
}
public static void main(String[] args) {
Scanner s=new Scanner(System.in);
int n=s.nextInt();
System.out.println(fab(n));
}
//13
下图为其递归搜索树:
🍅经典例题
(acwing92)递归实现指数型枚举
题解思路💡:
这一道题就可以将其抽象为一个递归问题,如果有n个数,则每一个数对应两种情况(选或不选),一个数完成后进行下一个数的判断。
可以这n个数的状态用一个长度为n的数组来记录,1表示选,2表示未选,数组遍历进行判断,最后输出结果,完成深度递归后进行回溯。
下图为用例输入3的递归搜索树:
代码实现:
import java.util.*;
public class Main {
static int N=16;
static int[]arr=new int[N];
//为了使得第几个数与数组的第几个元素相对应,所以数组长度加一
static int n;
public static void main(String[]args) {
Scanner s=new Scanner(System.in);
n=s.nextInt();
dfs(1);//从第一个数开始递归
}
public static void dfs(int u) {
if(u>n) {/*当u>n时,意味着整个数组所有元素已经进行了判断
,接下来就是遍历数组,根据对应的状态判断其是否需要输出
*/
for(int i=1;i<=n;i++) {
if(arr[i]==1) {
System.out.print(i+" ");
}
}
System.out.println();
return;
}
arr[u]=2;
dfs(u+1);
//该元素状态设为未选,然后递归下一个元素
arr[u]=1;
dfs(u+1);
//该元素状态设为已选,然后递归下一个元素
}
}
(acwing94)递归实现排列型枚举
原题链接
题解思路💡:
依次枚举每个位置可以放哪个数,需要参数如下:
- 1.数组(arr[N])用于存储填入的数据.
- 2.数组(boolean[N])用于判断某个数字是否可用.
- 3.目前所在位置.
代码实现:
import java.util.*;
public class Main {
static int n;
final static int N=10;
static int[]arr=new int[N];
static boolean []st=new boolean[N];
//默认为false,所以false为该数字可用,true为不可用
public static void dfs(int u) {
if(u>n) {//边界打印
for(int i=1;i<=n;i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
return;
}
for(int i=1;i<=n;i++) {
if(!st[i]) {
arr[u]=i;
st[i]=true;
dfs(u+1);
st[i]=false;//恢复现场
}
}
}
public static void main(String[]args) {
Scanner s=new Scanner(System.in);
n=s.nextInt();
dfs(1);
}
}
(acwing93)递归实现组合型枚举
原题链接
题解思路💡:
题目要求为字典序排序,只要我们按照升序递归,自然输出的即为正确顺序。
下边我们以五个数中取三个数为例,来梳理一下做这类题的思路:
我们会画出这样一棵递归树,如果要通过代码实现,我们需要通过三个参数。
- 1是数组(way[N]),用于存储于其中数字,当递归到最后一位时,按序输出数组;
- 2是递归位置(u),也就是考虑当前位置去存放哪个数;
- 3是最小开始放置的数字(start),因为题目要求是按序输出,第一个数如果是1,那么第二个数只能是比1大的数
代码实现:
import java.util.*;
public class Main {
final static int N=30;
static int[]way=new int[N];
static int n,m;
//通过设置全局变量,可以不用传参
public static void main (String[]args){
Scanner s=new Scanner(System.in);
n=s.nextInt();
m=s.nextInt();
dfs(1,1);//从第一个位置开始递归,最小开始填入的数也是1
}
public static void dfs(int u,int start) {
//if(u+n-start<m)
//return;
//上边两行代码实现的是递归树剪枝的过程,当剩余的数字不足以存储在数组内时,可以提前结束递归,提高代码运行效率
if(u>m) {//边界输出
for(int i=1;i<=m;i++) {
System.out.print(way[i]+" ");
}
System.out.println();
return;
}
for(int i=start;i<=n;i++) {
way[u]=i;//从start开始放置数字,保证顺序
dfs(u+1,i+1);//递归到下一个节点,且strat+1
way[u]=0;//恢复现场
}
}
}
🍅总结
这三种递归模型较为常见,递归可能较难为理解,但各位同学多进行思考、画图,也会慢慢掌握这种模型的。
这篇文章涉及到了指数型排列、全排列和组合型排列三种模型:
- 指数型排列就是依次枚举每个数字的情况,每个数字有选与不选两种情况,当递归到最底层时,根据判断数组中存储的每个数字选与不选的情况直接从1到n按序输出即可。
- 全排列是依次枚举每个位置可以放哪个数,设置判断数组判断每个数字是否使用,若为使用将该位置设为该数字,然后递归到下一个位置。
- 组合型排列也是依次枚举每个位置(共m个位置)放哪个数(但数的范围为start到n),因为要求按字典序,所以后一个数一定比前一个数字大,最后输出数组即可。
⚡️最后的话⚡️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁