菲波那切数列的递归与非递归解法以及青蛙跳台阶问题
2017-11-08 16:01
246 查看
说到求菲波那切数列中的第n个数,大家首先想到的就是递归解法,简单易懂。
但每一次的递归都会是一次函数的调用,会为参数和变量分配空间,所以递归的次数越多,就容易导致栈溢出。而且,当递归深度较深时,递归的效率会很低。所以,递归求解并不是一个高效的解法。这个时候用循环求解效率会高于递归。
我们来对比一下两者的效率:
题目一:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
当n = 1, 只有1种中跳法;当n = 2时,有两种跳法;当n = 3 时,有3种跳法;当n = 4时,有5种跳法;当n = 5时,有8种跳法;…….
经过分析,我们可以发现,这道题其实就是一个斐波那契数列问题,解法同上。
题目二:变态跳台阶。
一个台阶总共有n级,如果一次可以跳1级,也可以跳2级……它也可以跳上n级。此时该青蛙跳上一个n级的台阶总共有多少种跳法?
(1)分析:用Fib(n)表示青蛙跳上n阶台阶的跳法数,青蛙一次性跳上n阶台阶的跳法数1(n阶跳),设定Fib(0) = 1;
当n = 1 时, 只有一种跳法,即1阶跳:Fib(1) = 1;
当n = 2 时, 有两种跳的方式,一阶跳和二阶跳:Fib(2) = Fib(1) + Fib(0) = 2;
当n = 3 时,有三种跳的方式,第一次跳出一阶后,后面还有Fib(3-1)中跳法; 第一次跳出二阶后,后面还有Fib(3-2)中跳法;第一次跳出三阶后,后面还有Fib(3-3)中跳法
Fib(3) = Fib(2) + Fib(1)+Fib(0)=4;……..
题目三:矩形覆盖问题。
用2*1的小矩形,横着或竖着去覆盖更大的矩形,请问用8个2*1的小矩形无重叠地覆盖一个2*8的大矩形,总共有多少种方法?
我们把2*8的覆盖方法记为f(8).用第一个1*2的小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。当竖着放的时候,右边还剩下2*7的区域,这种情况的覆盖方法我们记为f(7).当把第一个小矩形横着放的时候,左下角必须放一个1*2的小矩形,而右边还有2*6的区域,这种情况下的覆盖方法称为f(6).所以,f(8)=f(7)+f(6).
通过上面的分析,我们可以看出,这道题其实也是斐波那契数列的应用。
long long Fibonacci(int n) { if (n <= 0) return 0; if (n == 1) return 1; return Fibonacci(n - 1) + Fibonacci(n - 2); }
但每一次的递归都会是一次函数的调用,会为参数和变量分配空间,所以递归的次数越多,就容易导致栈溢出。而且,当递归深度较深时,递归的效率会很低。所以,递归求解并不是一个高效的解法。这个时候用循环求解效率会高于递归。
long long Fib(unsigned int n) { int ret[2] = { 0, 1 }; if (n < 2) return ret ; long long fibOne = 1; long long fibTwo = 0; long long FibN = 0; for (unsigned int i = 2; i <= n; ++i) { FibN = fibOne + fibTwo; fibTwo = fibOne; fibOne = FibN; } return FibN; }
我们来对比一下两者的效率:
int main() { int start1 = GetTickCount(); Fibonacci(40); int end1 = GetTickCount(); cout << end1 - start1 << endl; int start2 = GetTickCount(); Fib(40); int end2 = GetTickCount(); cout << end2 - start2 << endl; system("pause"); return 0; }
题目一:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
当n = 1, 只有1种中跳法;当n = 2时,有两种跳法;当n = 3 时,有3种跳法;当n = 4时,有5种跳法;当n = 5时,有8种跳法;…….
经过分析,我们可以发现,这道题其实就是一个斐波那契数列问题,解法同上。
题目二:变态跳台阶。
一个台阶总共有n级,如果一次可以跳1级,也可以跳2级……它也可以跳上n级。此时该青蛙跳上一个n级的台阶总共有多少种跳法?
(1)分析:用Fib(n)表示青蛙跳上n阶台阶的跳法数,青蛙一次性跳上n阶台阶的跳法数1(n阶跳),设定Fib(0) = 1;
当n = 1 时, 只有一种跳法,即1阶跳:Fib(1) = 1;
当n = 2 时, 有两种跳的方式,一阶跳和二阶跳:Fib(2) = Fib(1) + Fib(0) = 2;
当n = 3 时,有三种跳的方式,第一次跳出一阶后,后面还有Fib(3-1)中跳法; 第一次跳出二阶后,后面还有Fib(3-2)中跳法;第一次跳出三阶后,后面还有Fib(3-3)中跳法
Fib(3) = Fib(2) + Fib(1)+Fib(0)=4;……..
//递归 long long Fib(int n) { if (n == 0) return 0; if (n == 1) return 1; if (n == 2) return 2; else return (2 * Fib(n - 1)); }
题目三:矩形覆盖问题。
用2*1的小矩形,横着或竖着去覆盖更大的矩形,请问用8个2*1的小矩形无重叠地覆盖一个2*8的大矩形,总共有多少种方法?
我们把2*8的覆盖方法记为f(8).用第一个1*2的小矩形去覆盖大矩形的最左边时有两个选择,竖着放或者横着放。当竖着放的时候,右边还剩下2*7的区域,这种情况的覆盖方法我们记为f(7).当把第一个小矩形横着放的时候,左下角必须放一个1*2的小矩形,而右边还有2*6的区域,这种情况下的覆盖方法称为f(6).所以,f(8)=f(7)+f(6).
通过上面的分析,我们可以看出,这道题其实也是斐波那契数列的应用。
nt fibonacci(int n) { int num1 = 1, num2 = 1, num3 = 0, i = 0; if (n <= 1) { return num1; } for (i = 1; i < n; i++) { num3 = num1 + num2; num1 = num2; num2 = num3; } return num3; }
相关文章推荐
- 青蛙跳台阶问题的递归思路
- 青蛙跳台阶问题的四种解法
- 递归的logN的优化(菲波那契数列,青蛙上台阶问题,母牛问题)!!!!
- 北大 算法 2.4 递归 汉诺塔问题手工解法以及编译过程
- N皇后问题递归与非递归解法
- 青蛙爬台阶问题的三种解法@python
- 走台阶问题的递归方法与非递归方法
- Java青蛙跳台阶的递归和非递归解法
- N皇后问题的递归与非递归解法
- 跳台阶问题 + 变态跳台阶问题 解法(动态规划递归 + 非递归)
- 用两种方法(递归和DP)实现了青蛙跳台阶
- 求约瑟夫环问题最后胜利者的一般解法以及数学推导方法
- Java学习.day_01(关于青蛙跳台阶的问题)
- 青蛙跳台阶问题
- 青蛙跳台阶问题
- 斐波那契数列的优化问题 青蛙跳台阶问题
- 青蛙跳台阶问题
- 分别使用一般递归的方法和模板元编程实现台阶问题。
- 汉诺塔问题以及递归
- 【面试题】剑指offer09--菲波那切数列中的变态青蛙问题