参考自:《剑指Offer——名企面试官精讲典型编程题》
题目:斐波那契数列
写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项。
主要思路:
方法1. 递归公式
f ( i ) = { f ( 0 ) = 0 f ( 1 ) = 1 f ( n ) = f ( n − 1 ) + f ( n − 2 ) n > 1 f(i)= \begin{cases} f(0) = 0 \\ f(1) = 1 \\ f(n) =f(n-1)+f(n-2) &n>1 \\ \end{cases} f(i)=⎩⎪⎨⎪⎧f(0)=0f(1)=1f(n)=f(n−1)+f(n−2)n>1
计算过程要避免重复计算,因此需要保存之前的计算结果。
方法2. 通项公式
关键点:避免重复计算,递归
时间复杂度:O(n)
public class FibonacciFormula {
private static long[] records;
public static void main(String[] args) {
int n = 7;
records = new long[n + 1];
//13
System.out.println(computeFibonacci(n));
System.out.println(computeFibonacci2(n));
System.out.println(fibonacciFormula(n));
}
/**
* 动态规划计算斐波那契数列
*
* @param n the n
* @return long
*/
private static long computeFibonacci(int n) {
if (records[n] != 0) {
return records[n];
}
if (n <= 1) {
return n;
}
long result = computeFibonacci(n - 1) + computeFibonacci(n - 2);
records[n] = result;
return result;
}
/**
* 循环计算斐波那契数列
*
* @param n the n
* @return long
*/
private static long computeFibonacci2(int n) {
if (n <= 1) {
return n;
}
long nMinusOne = 1;
long nMinusTwo = 0;
long fibN = 0;
for (int i = 2; i <= n; ++i) {
fibN = nMinusOne + nMinusTwo;
//更新f(n-2)
nMinusTwo = nMinusOne;
//更新f(n-1)
nMinusOne = fibN;
}
return fibN;
}
/**
* 通项公式计算斐波那契数列
*
* @param n the n
* @return long
*/
private static long fibonacciFormula(int n) {
double temp = Math.sqrt(5);
double result = (1 / temp) * (Math.pow((1 + temp) / 2, n) - Math.pow((1 - temp) / 2, n));
return (long) result;
}
}