最近去滴滴面试的一道题:斐波拉契数列非递归实现

斐波拉契数列这里复习一下:

0,1,1,2,3,5,8,13 ......

数列很简单,就是当前的项的值 等于 紧靠着的前面两项值的和, 立马想出来用递归几行代码就可以实现:

 1 /**
 2      * n是自然数
 3      * 递归实现
 4      * @param n
 5      * @return
 6      */
 7     public int fibonacci(int n) {
 8         if (n == 0)
 9             return 0;
10         if (n == 1 || n == 2)
11             return 1;
12         return fibonacci(n - 2) + fibonacci(n - 1);
13     }

由于递归循环调用方法,占用栈空间,n = 50 时,运行上面的代码,结果已经出不来了,

这里从上面的代码推出非递归实现:

 1 /**
 2      * n是自然数
 3      * 非递归实现
 4      *
 5      * @param n
 6      * @return
 7      */
 8     public int fibonacci(int n) {
 9         if (n == 0)
10             return 0;
11         if (n == 1 || n == 2)
12             return 1;
13         int a, b;
14         int sum = 0;
15         a = b = 1;
16         //这里从2开始遍历
17         for (int i = 2; i < n; i++) {
18             sum = a + b;
19             a = b;
20             b = sum;
21         }
22         return sum;
23     }

再次运行,结果很快就出来了

 结果倒是出来了,可是这样解的结果,时间复杂度是 O(N),有没有更快的解法呢,答案就是特征方程,求通向公式

拿出了数学书,重新复习了一下数列知识,推到了一下通向公式,过程如下:

 

由最终的结果可以看出这个问题最终转换成了求幂操作, 而求幂又可以用分治法的方式,使得最终的时间复杂度变成 O(Log2N)

 1       /**
 2      * 
 3      * @param base 底数
 4      * @param exponent 幂
 5      * @return
 6      */
 7     private double power(double base, int exponent) {
 8         if(exponent == 0)
 9             return 1;
10         if(exponent == 1)
11             return base;
12         double result = power(base, exponent >> 1);
13         result *= result;
14         if((exponent & 1) == 1)
15             result *= base;
16         return result;
17     }    

 

posted @ 2018-02-09 10:29  小-欢-欢  阅读(165)  评论(0编辑  收藏  举报