递归
首先,让我们先明确两个重要概念:
1.递归式(递归调用):将原问题分解成若干个子问题的手段
2* 递归边界*:分解的尽头
看一个例子:
2 5 8 11 14…你能发现其中的规律吗?
显然,这是一个等差数列,每项之间相差3,那么就可以写成A(n)=A(n-1)+3,即,当前项的值 = 前一项的值+3
假如现在我们要求出第6项的值,那就得知道第五项的值;要求第五项的值,就得知道第四项的值…
以此类推,则需知道第一项的值,而第一项前面已经没有项了,因此可以看出:
递归不能无限制,需要有起始项(递归边界),避免无限制递归
例题1:
使用递归方法求解等差数列2 5 8 11 14…第n项的值,要求输入n,输出第n项的值
思路:
1.定义一个函数,这个函数要求出等差数列的规律,并返回一个整数值res
注意:在编写函数的时候,如果函数有返回值,要先写好返回值,以免忘记
2.因为A(n)=A(n-1)+3,第n项的值与第(n-1)项的值有关,故可以调用函数来表示第(n-1)项的值,从而表示第n项,即,res=f(n-1)+3
3.设置一个起始项,即给n=1一个值,可以通过if语句进行
下面为相应的代码:
`#include <iostream>
using namespace std;
int f(int n){
int res;
if(n==1){
res=2;
}else{
res=f(n-1)+3;
}
return res;
}
int main(){
cout<<f(6);
return 0;
}
例题2 :
用递归求解n的阶乘
思路:
与上面同理,我们仍要构建一个函数,用F(n)表示n!,那么可以分析出:
F(n)=F (n - 1) * n,最后,给函数一个起始值就完成了
怎么样,是不是变得简单了?
下面是代码
#include <iostream>
using namespace std;
int F(int n){
int res;
if(n==1){
res=1;
}else{
res=F(n-1)*n;
}
return res;
}
int main(){
int n;
cin>>n;
cout<<F(n);
return 0;
}
再来看一个经典例子
例题3:
求Fibonacci 数列的第n项
思路
Fibonacci 数列(即斐波那契数列)是满足F(0)=1, F(1) =1,F(n) = F(n- 1)+F(n-2)(n≥2)的数列,数列的前几项为1,1,2,3,5,8, 13, 21,…
由于从定义中已经可以获知递归边界为 F(0)=1和F(1)=1,且递归式为F(n)=F(n-1)+F(n- 2)(n≥2),因此可以仿照求解n的阶乘的方法,写出求解 Fibonacci 数列第n项的程序:
#include <iostream>
using namespace std;
int F(int n){
int res;
if(n==0||n==1){
res=1;
}else {
res=F(n-1)+F(n-2);
}
return res;
}
int main(){
int n;
cin>>n;
cout<<F(n);
return 0;
}
但是,假如我们把n=50前的值依次输出,就会发现:刚开始,数据计算的很快,越往后越慢,
为什么会出现这样的现象呢?
原因是:
以求解第六项的值为例,需要知道第五项和第四项;想要求出第五项,则需知道第四项和第三项
…如果n=50,可想而知,求解的项数就会非常多,从而造成执行效率低
那么,如何解决这个问题呢?
答案是:不使用递归
我们可以用for循环,将每一项计算出来,并将其储存在数组中,因为该题数列是从F(0)开始,故与数组的下标是相对应的
#include <iostream>
using namespace std;
int main(){
int a[60]={0};
a[0]=1;
a[1]=1;
for(int i=2;i<=50;i++){
a[i]=a[i-1]+a[i-2];
}
for(int i=0;i<=50;i++){
cout<<i<<":"<<a[i]<<endl;
}
return 0;
}
可以看出,输出的速度快了很多,这是因为没有重复计算的部分,但是后面却出现了错误的数据
这个问题与n的数据类型有关,因为求解的结果太大,超出了int的范围(-2的31次幂~2的31次幂-1,即-2147483648 ~2147483647),此时可以将int更换为long long
我们将这种方式称为递推
看下面这道题:
例题4
在墙角按照规律堆放着一些完全相同的正方体小块儿,只需要知道层数就可以计算所有小块的数量。输入: 一个整数n(1<-n<-100 ),代表层数。输出:一个整数,表示这堆小块儿的总量
#include <iostream>
using namespace std;
int main(){
int n;
cin>>n;
int level=1;//第一层为1
int sum=1;//计算总数
for(int i=2;i<=n;i++){
level+=i;
sum+=level;
}
cout<<sum;
return 0;
}
今天的学习就到这里啦~
让我们继续坚持下去吧!
加油~
总有远方可以奔赴,
总有好事水到渠成,
做有序的自己,
等待万物更新。