递归算法经典例题分析

本篇用C++语言实现上述部分递归算法的例题,并附上详细的讲解。

1. 斐波那契数列

斐波那契数列(Fibonacci sequence),又称黄金分割数列,是由意大利数学家莱昂纳多·斐波那契(Leonardo Fibonacci)在他的著作《Liber Abaci》中首先描述的一个数列。这个数列在自然界和数学中都有广泛的应用,特别是在计算机科学、生物学、物理学、艺术等领域。

斐波那契数列是这样一个数列:每个数是前两个数的和。数列以0和1开始,即:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

具体地,数列的定义如下:

  • F(0) = 0
  • F(1) = 1
  • 对于所有 n > 1,有 F(n) = F(n-1) + F(n-2)

代码实现

#include <iostream> 

int fibonacci(int n) { 
if (n <= 1) { 
return n; 
} else { 
return fibonacci(n - 1) + fibonacci(n - 2); 
} 
} 


int main() { 
int n = 10; 
std::cout << "Fibonacci number at position " << n << " is " << fibonacci(n) << std::endl; 
return 0; 
}

讲解

斐波那契数列是一个经典的递归问题。在这个实现中,我们定义了一个fibonacci函数,它接受一个整数n作为参数,并返回斐波那契数列中第n个位置的值。如果n小于或等于1,函数直接返回n(因为斐波那契数列的前两个数是0和1)。否则,函数递归地调用自身两次,分别计算前一个数和前两个数的值,并将它们相加返回。

2. 阶乘计算

阶乘(Factorial)是所有小于及等于该数的正整数的积,并且0的阶乘为1。通常,一个非负整数n的阶乘写作n!(读作n的阶乘)。

定义如下:

  • 如果n是非负整数,那么n! = n × (n-1) × (n-2) × ... × 3 × 2 × 1。
  • 特别地,定义0! = 1。

阶乘的概念起源于组合数学和排列组合中,它表示了从n个不同元素中取出n个元素的所有排列的个数。

例如:

  • 5! = 5 × 4 × 3 × 2 × 1 = 120
  • 4! = 4 × 3 × 2 × 1 = 24
  • 3! = 3 × 2 × 1 = 6
  • 2! = 2 × 1 = 2
  • 1! = 1
  • 0! = 1(根据定义)

阶乘的增长速度非常快,随着n的增加,n!的值迅速增大。阶乘在数学、计算机科学、统计学等领域都有广泛的应用,特别是在计算组合数、概率和统计学中的排列问题时。

代码实现

#include <iostream> 

int factorial(int n) { 
if (n == 0) { 
return 1; 
} else { 
return n * factorial(n - 1); 
} 
} 


int main() { 
int n = 5; 
std::cout << "Factorial of " << n << " is " << factorial(n) << std::endl; 
return 0; 
}

讲解

阶乘计算也是一个常见的递归问题。在这个实现中,我们定义了一个factorial函数,它接受一个整数n作为参数,并返回n的阶乘。如果n等于0,函数返回1(因为0的阶乘是1)。否则,函数递归地调用自身,计算n-1的阶乘,并将结果与n相乘返回。

3. 爬楼梯

假如这里有 n 个台阶,每次你可以跨 1 个台阶或者 2 个台阶,请问走这 n 个台阶有多少种走法?如果有 7 个台阶,你可以 2,2,2,1 这样子上去,也可以 1,2,1,1,2 这样子上去,总之走法有很多,那如何用编程求得总共有多少种走法呢?

代码实现

#include<iostream>
using namespace std;
int f(int n){
	if(n == 1)
		return 1;
	if(n == 2)
		return 2;
	return f(n-1)+f(n-2);
}
int main(){
	int n;
	cin >> n;
	cout << f(n);
	return 0;
} 

讲解

我们仔细想下,实际上,可以根据第一步的走法把所有走法分为两类,第一类是第一步走了 1 个台阶,另一类是第一步走了 2 个台阶。所以 n 个台阶的走法就等于先走 1 阶后,n-1 个台阶的走法 加上先走 2 阶后,n-2 个台阶的走法。用公式表示就是:

f(n) = f(n-1)+f(n-2)

有了递推公式,递归代码基本上就完成了一半。我们再来看下终止条件。当有一个台阶时,我们不需要再继续递归,就只有一种走法。所以 f(1)=1。这个递归终止条件足够吗?我们可以用 n=2,n=3 这样比较小的数试验一下。

n=2 时,f(2)=f(1)+f(0)。如果递归终止条件只有一个 f(1)=1,那 f(2) 就无法求解了。所以除了 f(1)=1 这一个递归终止条件外,还要有 f(0)=1,表示走 0 个台阶有一种走法,不过这样子看起来就不符合正常的逻辑思维了。所以,我们可以把 f(2)=2 作为一种终止条件,表示走 2 个台阶,有两种走法,一步走完或者分两步来走。

所以,递归终止条件就是 f(1)=1,f(2)=2。这个时候,你可以再拿 n=3,n=4 来验证一下,这个终止条件是否足够并且正确。

我们把递归终止条件和刚刚得到的递推公式放到一起就是这样的:

f(1) = 1;

f(2) = 2;

f(n) = f(n-1)+f(n-2)

有了这个公式,我们转化成递归代码就简单多了。最终的递归代码是这样的:

int f(int n) {

if (n == 1) return 1;

if (n == 2) return 2;

return f(n-1) + f(n-2);

}

  • 20
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值