509. 斐波那契数(简单)

1,问题描述

509. 斐波那契数

难度:简单

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 01 开始,后面的每一项数字都是前面两项数字的和。也就是:

1
2
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1

给定 n ,请计算 F(n)

示例 1:

1
2
3
输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

1
2
3
输入:n = 3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

1
2
3
输入:n = 4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

  • 0 <= n <= 30

2,初步思考

​ 这个是经典的斐波那契数列,模拟法、dp、递归都可以解决,最快的还是数学方法直接算出结果

3,代码处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
public class _509斐波那契数 {

// 解法:矩阵快速幂
// 数学素养要好才行!!!计算步骤其实更多了!!!
public int fib_matrix(int n) {
if (n < 2) {
return n;
}
int[][] q = {{1, 1}, {1, 0}};
int[][] res = pow(q, n - 1);
return res[0][0];
}

public int[][] pow(int[][] a, int n) {
int[][] ret = {{1, 0}, {0, 1}};
while (n > 0) {
if ((n & 1) == 1) {
ret = multiply(ret, a);
}
n >>= 1;
a = multiply(a, a);
}
return ret;
}

public int[][] multiply(int[][] a, int[][] b) {
int[][] c = new int[2][2];
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
c[i][j] = a[i][0] * b[0][j] + a[i][1] * b[1][j];
}
}
return c;
}

// 解法:模拟法
public int fib_simulate(int n) {
if (n < 2) {
return n;
}
int start = 0, end = 1;
for (int i = 2; i <= n; i++) {
int temp = end;
end = start + end;
start = temp;
}
return end;
}

// 斐波那契数 F(n) 是齐次线性递推
public int fib_math_(int n) {
double sqrt5 = Math.sqrt(5);
double fibN = Math.pow((1 + sqrt5) / 2, n) - Math.pow((1 - sqrt5) / 2, n);
return (int) Math.round(fibN / sqrt5);
}

// 数学方法求解
// 所有的数据最终都是会变为0,1的个数求解
// 时间复杂度:O(n),空间复杂度:O(1),只用遍历一次
public int fib_math_sum(int n) {
if (n <= 1) return n;
int beforeIdx = n, beforeCnt = 1, afterCnt = 0;
while (beforeIdx > 1) {
beforeIdx--;
int tempCnt = beforeCnt;
beforeCnt = beforeCnt + afterCnt;
afterCnt = tempCnt;
}
return beforeCnt;
}


// 动态规划:0ms、击败100%
// 时间复杂度:O(n),空间复杂度:O(n)
public int fib_dynamic(int n) {
dp = new int[n + 1];
return fib_dp(n);
}

int[] dp;

private int fib_dp(int n) {
if (n <= 1) return n;
if (dp[n] != 0) return dp[n];
dp[n] = fib_dp(n - 1) + fib_dp(n - 2);
return dp[n];
}

// 递归:9ms、击败21.61%
// 重复计算有点多,优化一下用空间换时间
// 时间复杂度:O(2^n),空间复杂度:O(1)
public int fib_recursion(int n) {
if (n <= 1) return n;
return fib_recursion(n - 1) + fib_recursion(n - 2);
}

public static void main(String[] args) {
_509斐波那契数 fib = new _509斐波那契数();
System.out.println(fib.fib_simulate(10));
System.out.println(fib.fib_dynamic(10));
}
}