题目一:实现一个函数,输入n,求斐波那契数列的第n项。斐波那契数列的定义如下:
看到这个最简单想到的方法是采用递归来实现
功能函数:
long long Fibonacci(int n) { if(n<0) return; if(n==0) return 0; if(n==1) return 1; if(n>1) return Fibonacci(n-1)+Fibonacci(n-2); }
程序分析:
采用递归来解决这一问题,会带来严重的效率问题。比如:要求f(10),如下图所示
可以看到,上面图示中有很多重复结点,而且重复结点会随着n的增大而急剧增加,意味着计算量也会随着n的增大而急剧增加。
针对上述递归方法的低效率,做如下改进:
思路1:可以把已经得到的数列中间项保存起来,如果下次需要计算的时候先查找一下,如果之前已经计算过就不用重复计算了。
思路2:可以从下往上计算,首先根据f(0)和f(1)算出f(2),再根据f(1)和f(2)算出f(3)......依次类推,直到算出f(n)即可。
功能函数:
long long one=0; long long two=1; long long result=0; long long Fibonacci(int n) { int i; if(n<0) return; if(n==0) return 0; if(n==1) return 1; for(i=2;i<=n;i++) { result=one+two; one=two; two=result; } return result; }
注意:如果将长整型变量one、two、result放在函数体内,变为局部变量,编译时出错。
原因是:编译器栈空间有限 分配不了那么大的局部变量。定义在外面,即为全局变量,是存储在全局区,不在栈区
测试程序:
int main() { int a,b,sum=0; printf("递归方法 "); printf("请输入一个数:"); scanf("%d",&a); sum=Fibonacci_1(a); printf("输入的数%d的斐波那契数列的第%d项为:%d ",a,a,sum); printf(" "); printf("非递归方法 "); printf("请输入一个数:"); scanf("%d",&b); sum=Fibonacci_2(b); printf("输入的数%d的斐波那契数列的第%d项为:%d ",b,b,sum); printf(" "); system("pause"); return 1; }
测试结果:
题目二:实现一个函数:一个楼梯有50个台阶,每一步可以走一个台阶,也可以走两个台阶,请问走完这个楼梯共有多少种方法?
分析:
1步台阶只有1种走法(1)
2步台阶2种(11、2)
3步台阶有3种(111、12、21)
4步台阶有5种(1111、112、121、211、22)
5步台阶有8种(11111、1112、1121、1211、122、2111、212、221)
6步台阶有13种(111111、11112、11121、11211、1122、12111,1212、1221、2111、2112、2121、2211、222)
..............
假设走完k个台阶有f(k)种走法。
k = 1时,f(k) = 1
k = 2时,f(k) = 2
k = n时,第一步走一个台阶,剩n-1个台阶,有f(n - 1)种走法。第一步走两个台阶,剩n-2个台阶,有f(n - 2)种走法。所以共有f(n - 1) + f(n - 2)种走法。
于是有如下公式:
显然此题与上题类似!