【C++】----递归与递推~

递归

首先,让我们先明确两个重要概念:
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;
}               

今天的学习就到这里啦~

让我们继续坚持下去吧!
加油~

总有远方可以奔赴,
总有好事水到渠成,
做有序的自己,
等待万物更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值