本篇用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); | |
} |