解题思路:
(1)斐波那契数列又称兔子数列,第一二项为1,从第三项开始,都等于前两项之和,如果要求第n项,那么必须知道第n-1项和第n-2项,一次类推,发现要求目标值,总要求比它规模更小的子问题,而且最小的子问题我们是知道的,即第一项是1,第二项也是1,满足递归的三要素,所以尝试用递归的写法
(2)设f(n)函数求斐波那契数列的第n项,那么关系表达式为f(n)=f(n-1)+f(n-2),出口条件为if(n==1||n==2)return 1;
#include<bits/stdc++.h>
using namespace std;
int f(int x)
{
if(x==1||x==2)//递归出口
return 1;
else
return f(x-1)+f(x-2);//层层递进
}
int main()
{
int n;
cin>>n;
cout<<f(n);
return 0;
}
优化思路:
(1)当求第5项的时候,发现要求第3项和第4项,要求第3项的时候求了第1项和第2项,要求第4项的时候,求第3项和第2项,发现第3项重复了,造成了子问题重叠,当n比较大的时候,会有很多子问题重叠,造成运行效率低下
(2)该如何优化呢?求过的其实我们可以存到数组中,不用再求,每次函数递进的时候,先判断是否为出口,然后判断该子问题是否被求过,如果被求过,直接返回结果即可,否则的话,继续递归,这样,就免去了很多不必要的重复计算,也叫做记忆化搜索!
(3)设int d 【maxn】数组用来存储求解过的子问题,因为数组初始化都为0,那么只需判断该项也就是d【n】是否为0,如果是,则继续调用,如果不是,说明已被求解过,直接返回d【n】即可
#include<bits/stdc++.h>
using namespace std;
int d[100];
int f(int x)
{
if(x==1||x==2)//递归出口
return 1;
if(d[x]==0)//如果该子问题没有被求解过
d[x]=f(x-1)+f(x-2);//继续递归
return d[x];//最后返回d[x]
}
int main()
{
int n;
cin>>n;
cout<<f(n);
return 0;
}