import com.google.common.base.Preconditions;
/**
* 斐波纳契数列:
*
* 定义:
* { 0 n=0
* f(n)=| 1 n=1
* { f(n-1) + f(n-2) n>1
*
* 问题:求斐波那契数列第n项的值。
*
* 说明:
* 1)递归方式的时间复杂度为指数级别O(2^n)
* 2)从下往上计算的方式,时间复杂度为线性级别O(n)
*
*/
public class Fibonacci {
/**
* 递归方式求解斐波那契数列的过程,可以用下图来描述:
*
* f(10)
* / \
* / \
* f(9) f(8)
* / \ / \
* f(8) f(7) f(7) f(6)
* / \ / \ / \
* f(7) f(6) f(6) f(5) f(6) f(5)
*
* 重复的节点数会随着n的增大而急剧增大,故递归的过程中,发生了大量重复的计算,导致时间复杂度变为指数级别O(2^n)。
*
* @param n
* @return
*/
public static long getFibonacci(long n) {
Preconditions.checkArgument(n >= 0);
if (n == 0) return 0;
if (n == 1) return 1;
return getFibonacci(n-1) + getFibonacci(n-2);
}
/**
* 从下往上计算,从而避免重复计算。
*
* 即:根据f(0)、f(1)计算出f(2),再根据f(1)、f(2)计算出f(3),,
*
* 时间复杂度为O(n)
*
* @param n
* @return
*/
public static long getFibonacciByNonRecursion(long n) {
Preconditions.checkArgument(n >= 0);
if (n == 0) return 0;
if (n == 1) return 1;
long fiboNminusTwo = 0; // f(0)
long fiboNminusOne = 1; // f(1)
long fiboN = 0; // f(n)
/**
* 第一次:f(2)= f(0) + f(1)
* 第二次:f(3)= f(1) + f(2)
* 第三次:f(4)= f(2) + f(3)
*/
for (int i = 2; i <= n; i++) {
fiboN = fiboNminusTwo + fiboNminusOne;
fiboNminusTwo = fiboNminusOne;
fiboNminusOne = fiboN;
}
return fiboN;
}
public static void main(String[] args) {
long num = getFibonacciByNonRecursion(10L);
long num2 = getFibonacci(10L);
System.out.println(num);
System.out.println(num2);
}
}