一、递归的概念
直接或间接的调用自身的算法叫递归算法。用函数自身给出定义的函数称为递归函数。
运用递归的比较简单的例子有:阶乘函数,Fibonacci函数等
递归的主要解题思路:
1、明确函数作用
2、寻找递归结束条件
3、找函数的等价关系
为了进一步理解递归的含义,从以下几个题进行介绍:
二、具体例题:
难度:简单
题目来源:牛客na
链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述一:
给你一个数,让他进行巴啦啦能量,沙鲁沙鲁,小魔仙大变身,如果进行变身的数不满足条件的话,就继续让他变身。。。直到满足条件为止。
巴啦啦能量,沙鲁沙鲁,小魔仙大变身:对于一个数,把他所有位上的数字进行加和,得到新的数。
如果这个数字是个位数的话,那么他就满足条件。
输入描述:
给一个整数数字n(1<=n<=1e9)。
输出描述:
输出由n经过操作满足条件的数
示例1
输入
12
12
输出
3
3
说明
12 -> 1 + 2 = 3
解析:本题需要用到%和/这种算术运算符和递归
1、分析题目:
如12->1+2=3 (个位数则不继续分解,需要进行返回)
如231->23+1->24->2+4->6(个位数不继续分解)
231->2+3+1->6(个位数不进行分解) 这个231的分解分别对应着两种解法:
第一种解法:当然,如果没有发现这种规律可以使用第二种解法
#include<stdio.h>
int add(int n)
{
if(n/10==0)
{
return n;
}
else{
return add(n%10+n/10);
}
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",add(n));
}
第二种解法:设置了x来储存,给出例子进行验证会比较好理解,如132:
首先,我们需要通过while循环取到一个数的每一位并进行相加
进入while循环第一次:x=2;n=13; 第二次:x=3+2=5; n=1; 第三次:x=5+1=6;n=0
其次,进行递归,若是一个数则返回n,若不是,继续while把每一位进行相加
递归:add(6):判断是不是一个数,其实这里可以直接写if(n<10)来判断,有时候突然没想到哈哈哈
#include<stdio.h>
int add(int n)
{
int x=0;
if(n/10==0)
{
return n;
}
while(n){
x=x+n%10;
n=n/10;
}
return add(x);
}
int main()
{
int n;
scanf("%d",&n);
printf("%d",add(n));
}
题目描述二
利用更相减损术求两个整数的最大公约数,即每次将较大的数变成大数减去小数的值
输入描述:
输入两个正整数,范围在1000000以内
输出描述:
输出一个整数
示例1
输入
4 6
4 6
输出
2
2
解析:本题用到递归,更相减损失数,这也是一种计算最大公约数的方法呢
分析题目:首先一定要分析这个题目的实现,是怎么得到这个结果的,可以在纸上演算一遍
据分析:更相减损失数:是不断的更新较大值,怎么更新呢,是通过不断的较大值-较小值的结果更新
举个例子说明(递归的理解):4 6 首先6>4,则更新6为6-4=2,所以这个例子变为了 4 2;
其次4>2,则更新4为4-2=2,所以这个例子变为了 2 2;
当最后更新出来的两个数字相等时,得到了这个最大公约数。
#include<stdio.h>
int cha(int a,int b)
{
if(a==b)
{
return a;
}
else{
if(a>b)
{
return cha(a-b,b);
}
else{
return cha(a,b-a);
}
}
}
int main()
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d",cha(a,b));
return 0;
}
题目描述三
小q最近迷上了各种好玩的数列,这天,他发现了一个有趣的数列,其递推公式如下:
f[0]=0 f[1]=1;
f[i]=f[i/2]+f[i%2];(i>=2)
现在,他想考考你,问:给你一个n,代表数列的第n项,你能不能马上说出f[n]的值是多少,以及f[n]所代表的值第一次出现在数列的哪一项中?(这里的意思是:可以发现这个数列里某几项的值是可能相等的,则存在这样一个关系f[n'] = f[n] = f[x/2]+f[x%2] = f[x]...(n'<n<x) 他们的值都相等,这里需要你输出最小的那个n'的值)(n<10^18)
输入描述:
输入第一行一个t 随后t行,每行一个数n,代表你需要求数列的第n项,和相应的n' (t<4*10^5)
输出描述:
输出每行两个正整数 f[n]和n',以空格分隔
示例1
输入
2 0 1
输出
0 0 1 1
解析:本题用到递归
分析题目:该题一定要看懂 题目(呜呜呜,刚开始一直没看懂这个题目)经过演算,我发现
f(1)=1 2^1-1
f(4)=1 2^1-1
f(8)=1 2^1-1
这个题目就是要找到相同结果的最小的那个x 和它的值 显然这个例子是1
#include<stdio.h>
#include<math.h>
long int di(long int n)
{
if(n==0)
{
return 0;
}
else if(n==1)
{
return 1;
}
else{
return di(n/2)+di(n%2);
}
}
int main()
{
long int a;
scanf("%ld",&a);
long int b;
long int i;
for(i=0;i<a;i++)
{
scanf("%ld",&b);
long int t;
long int m;
t=di(b);
m=pow(2,t)-1;
printf("%ld %ld\n",t,m);
}
return 0;
}
难度:适中
全排列问题:
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
现有一例子:arr[1,2,3] 给出全排列的所有组合
核心算法:Swap是需要自己写的交换函数
void Perm(int* br, int k, int m)
{
if (k == m)
{
for (int i = 0; i <= m; ++i)
{
printf("%d ", br[i]);
}
printf("\n");
}
else
{
for (int j = k; j <= m; ++j)
{
Swap(br[j], br[k]);
Perm(br, k + 1, m);
Swap(br[j], br[k]);
}
}
}
分析问题:k是第一个元素的坐标,m是指向最后一个元素的坐标,个人刚开始不理解,建议可以动笔画画,或者单步调试。理解是怎么递归的。
算法 | 全排列问题(图文详解)-CSDN博客 可见这个博主的文章,个人觉得讲得很清楚。
整数划分问题:
题目描述
整数划分就是将一个正整数表示成一系列正整数之和,问有多少种不同划分方案! 例如整数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
输入正整数n,计算n有多少种不同划分方案。
输入
包括多组数据,每组1个整数n。
输出
n的不同划分方案种数。
样例输入 Copy
1 2 3 4 5 6
样例输出 Copy
1 2 3 5 7 11
分析问题:
该题目是将n划分为一系列整数和,在n的所有划分中,将最大加数n,不大于m的划分个数记为q(n,m):
当m=1 或者n=1时,划分只有一种可能性,即为1 1 1 1 1 1 1很多个1.
当n<m时,应变为q(n,n);
当n=m时,1+q(n,n-1)
当n>m>1时,q(n,m-1)+q(n-m,m)
具体代码:
#include<stdio.h>
int divide(int n,int m)
{
if(m==1)
{
return 1;
}
if(n<m)
{
return divide(n,n);
}
if(n==m)
{
return 1+divide(n,n-1);
}
if(n>m&&n>1&&m>1)
{
return divide(n,m-1)+divide(n-m,m);
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int p=0;
p=divide(n,n);
printf("%d\n",p);
}
}