一、基础问题
1.问题描述
以下数列 0 1 1 2 3 5 8 13 21 ... 被称为斐波纳契数列。
这个数列从第 3项开始,每一项都等于前两项之和。
输入一个整数 N,请你输出这个序列的第N项。
2.解题方法及代码
(1)递归
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int n;
int f(int n){
if(n == 1) return 0;
if(n == 2) return 1;
return f(n-1) + f(n-2);
}
int main(){
scanf("%d", &n);
printf("%d", f(n));
return 0;
}
(2)递推
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 50;
int n;
int a[N];
int main(){
scanf("%d", &n);
a[1] = 0;
a[2] = 1;
for(int i = 3; i <= n; ++ i){
a[i] = a[i-1] + a[i-2];
}
printf("%d", a[n]);
return 0;
}
二、进阶问题
1.问题描述
以下数列 0 1 1 2 3 5 8 13 21 ... 被称为斐波纳契数列。
这个数列从第3项开始,每一项都等于前两项之和。
输入一个整数N,请你输出这个序列的前N项。
输入格式
一个整数 N。
输出格式
在一行中输出斐波那契数列的前N项,数字之间用空格隔开。
数据范围
0<N<46
输入样例:
5
输出样例:
0 1 1 2 3
2.分析
进阶问题与基础问题相比,最大的区别是计算次数变多了。对于递归方法来说,就是调用递归函数的次数大大增加,当n较大时,会导致超时。
观察易得,若利用基础的递归方法来解会有很多重复计算,可以在计算过程中用数组进行记录(记忆化搜索)。
3.解题方法及代码
(1)记忆化搜索(基础递归解法进阶)
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 50;
int n;
int a[N];
int f(int n){
if(n == 1) a[1] = 0;
else if(n == 2) a[2] = 1;
else if(!a[n]) a[n] = f(n-1) + f(n-2);
return a[n];
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
printf("%d ", f(i));
}
return 0;
}
(2)递推
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 50;
int a[N];
int main(){
int n;
scanf("%d", &n);
a[1] = 0;
a[2] = 1;
for(int i = 3; i <= n; ++ i){
a[i] = a[i-1] + a[i-2];
}
for(int i = 1; i <= n; ++ i){
printf("%d ", a[i]);
}
return 0;
}
(3)不需开辟数组空间的递推解法
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 50;
int n;
int a[N];
int main(){
scanf("%d", &n);
int a = 0, b = 1, c;
for(int i = 1; i <= n; ++ i){
printf("%d ", a);
c = a + b;
a = b;
b = c;
}
return 0;
}