斐波那契数列和青蛙跳台阶问题

582 阅读2分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动。

斐波那契数列问题

写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。

递归思路

斐波那契数列为; 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55

当我们求数列第n项的值时, 也就是在求第n-1项和第n-2项的和, 也就是f(n) = f(n-1) + f(n-2)

代码 - 递归方式

优点: 代码实现简单易于理解

缺点: 空间复杂度和时间复杂度都很高

 public int fibonacciByRecursive(int n) {
     if (n == 0) return 0;
     if (n == 1) return 1;
     return fibonacciByRecursive(n - 1) + fibonacciByRecursive(n - 2);
 }

循环思路

根据f(0)和f(1)解出f(2), 再根据f(1)和f(2)解出f(3), 依此类推, 根据f(n-2)和f(n-1)解出f(n)

代码 - 循环方式

优点: 它的时间复杂度是O(n), 空间复杂度为O(1)

缺点: 它好像没什么缺点

 public int fbonacciByCirculation(int n) {
     if (n == 0) return 0;
     if (n == 1) return 1;
 ​
     int first = 0;
     int second = 1;
     int result = 0;
     
     for (int i = 2; i <= n; i++) {
         // f(n) = f(n-1) + f(n-2)
         result = first + second;
         
         // 更改n-2项的值
         first = second;
         
         // 记录n-1项的值
         second = result;
     }
     return result;
 }

青蛙上台阶问题

思路

当有1级台阶时, 只有1种跳法

当有2级台阶时, 有2种跳法

当有3级台阶时, 它有可能是从第一级台阶跳过来, 也有可能是从第二级台阶跳过来, 所以是第1级台阶的跳法数目和第二级台阶的跳法数目

当有n级台阶时, 它有可能是从第n-2级台阶跳过来, 也有可能是从第n-1级台阶跳过来, 所以是第n-2级台阶的跳法数目和第n-1级台阶的跳法数目的总和, 即f(n) = f(n-2) + f(n-1)

因此, 该问题是也是一个斐波那契数列问题

代码 - 循环方式

     public int numWaysByCirculation(int n) {
         if (n == 0 || n == 1) return 1;
         if (n == 2) return 2;
 ​
         int first = 1;
         int second = 2;
         int result = 0;
         for (int i = 3; i <= n; i++) {
             result = (first + second) % 1000000007;
             first = second;
             second = result;
         }
         return result;
     }

代码 - 递归方式

 public int numWaysByRecursive(int n) {
     if (n == 0 || n == 1) return 1;
     if (n == 2) return 2;
     return numWaysByRecursive( n - 1) + numWaysByRecursive(n - 2);
 }

总结

我们要充分理解递归和循环的思想, 在使用递归的时候, 虽然它的代码很简单, 易于理解, 但是如果数据量大的情况下, 它会有很严重的性能问题, 耗时也会指数增长. 所有的递归解法, 我们都可以转换成循环思想来替代实现. 因此我们要慎用递归, 巧用循环.