1,递归解决
这题非常简单,我们直接按照公式来就可以了F(n) = F(n - 1) + F(n - 2)
,但要做好边界条件的判断F(0) = 0,F(1) = 1
public int Fibonacci(int n) { if (n < 2) return n; return Fibonacci(n - 1) + Fibonacci(n - 2); }
之前讲《356,青蛙跳台阶相关问题》的时候也提到过斐波那契数列,斐波那契数列递归的时候会造成大量的重复计算,比如就计算fib(6)为例来看下
我们看到上面相同颜色的都是重复计算,当n越大,重复的越多,所以我们可以使用一个map把计算过的值存起来,每次计算的时候先看map中有没有,如果有就表示计算过,直接从map中取,如果没有就先计算,计算完之后再把结果存到map中。
public int Fibonacci(int n) { return helper(n, new HashMap()); } private int helper(int n, Map<Integer, Integer> map) { if (n < 2) return n; if (map.containsKey(n)) return map.get(n); int first = helper(n - 1, map); int second = helper(n - 2, map); int res = (first + second); map.put(n, res); return res; }
2,非递归解法
我们还可以把斐波那契递归改为非递归,代码很简单,可以看下
public int Fibonacci(int n) { int first = 0; int second = 1; while (n-- > 0) { int temp = first + second; first = second; second = temp; } return first; }
3,公式计算
在《356,青蛙跳台阶相关问题》的最后还提到斐波那契数列实际上是有个公式的,
所以我们还可以通过公式来计算。
public int Fibonacci(int n) { double fun1 = (1 + Math.sqrt(5)) / 2; double fun2 = (1 - Math.sqrt(5)) / 2; return (int) Math.round((Math.pow(fun1, n) - Math.pow(fun2, n)) / Math.sqrt(5)); }
4,直接查找
因为在int范围内,斐波那契数列的值是有限的,并且也不多,所以可以使用查表的方法解决
public int Fibonacci(int n) { int[] table = {0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040 , 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986}; return table[n]; }
我把部分算法题整理成了PDF文档,截止目前总共有900多页,大家可以下载阅读
链接:https://pan.baidu.com/s/1hjwK0ZeRxYGB8lIkbKuQgQ
提取码:6666