Skip to content

Commit 2fed35c

Browse files
committed
添加 problem 509
1 parent 57299ec commit 2fed35c

File tree

3 files changed

+220
-0
lines changed

3 files changed

+220
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package leetcode
2+
3+
import "math"
4+
5+
// 解法一 递归法 时间复杂度 O(2^n),空间复杂度 O(n)
6+
func fib(N int) int {
7+
if N <= 1 {
8+
return N
9+
}
10+
return fib(N-1) + fib(N-2)
11+
}
12+
13+
// 解法二 自底向上的记忆化搜索 时间复杂度 O(n),空间复杂度 O(n)
14+
func fib1(N int) int {
15+
if N <= 1 {
16+
return N
17+
}
18+
cache := map[int]int{0: 0, 1: 1}
19+
for i := 2; i <= N; i++ {
20+
cache[i] = cache[i-1] + cache[i-2]
21+
}
22+
return cache[N]
23+
}
24+
25+
// 解法三 自顶向下的记忆化搜索 时间复杂度 O(n),空间复杂度 O(n)
26+
func fib2(N int) int {
27+
if N <= 1 {
28+
return N
29+
}
30+
return memoize(N, map[int]int{0: 0, 1: 1})
31+
}
32+
33+
func memoize(N int, cache map[int]int) int {
34+
if _, ok := cache[N]; ok {
35+
return cache[N]
36+
}
37+
cache[N] = memoize(N-1, cache) + memoize(N-2, cache)
38+
return memoize(N, cache)
39+
}
40+
41+
// 解法四 优化版的 dp,节约内存空间 时间复杂度 O(n),空间复杂度 O(1)
42+
func fib3(N int) int {
43+
if N <= 1 {
44+
return N
45+
}
46+
if N == 2 {
47+
return 1
48+
}
49+
current, prev1, prev2 := 0, 1, 1
50+
for i := 3; i <= N; i++ {
51+
current = prev1 + prev2
52+
prev2 = prev1
53+
prev1 = current
54+
}
55+
return current
56+
}
57+
58+
// 解法五 矩阵快速幂 时间复杂度 O(log n),空间复杂度 O(log n)
59+
// | 1 1 | ^ n = | F(n+1) F(n) |
60+
// | 1 0 | | F(n) F(n-1) |
61+
func fib4(N int) int {
62+
if N <= 1 {
63+
return N
64+
}
65+
var A = [2][2]int{
66+
{1, 1},
67+
{1, 0},
68+
}
69+
A = matrixPower(A, N-1)
70+
return A[0][0]
71+
}
72+
73+
func matrixPower(A [2][2]int, N int) [2][2]int {
74+
if N <= 1 {
75+
return A
76+
}
77+
A = matrixPower(A, N/2)
78+
A = multiply(A, A)
79+
80+
var B = [2][2]int{
81+
{1, 1},
82+
{1, 0},
83+
}
84+
if N%2 != 0 {
85+
A = multiply(A, B)
86+
}
87+
88+
return A
89+
}
90+
91+
func multiply(A [2][2]int, B [2][2]int) [2][2]int {
92+
x := A[0][0]*B[0][0] + A[0][1]*B[1][0]
93+
y := A[0][0]*B[0][1] + A[0][1]*B[1][1]
94+
z := A[1][0]*B[0][0] + A[1][1]*B[1][0]
95+
w := A[1][0]*B[0][1] + A[1][1]*B[1][1]
96+
A[0][0] = x
97+
A[0][1] = y
98+
A[1][0] = z
99+
A[1][1] = w
100+
return A
101+
}
102+
103+
// 解法六 公式法 f(n)=(1/√5)*{[(1+√5)/2]^n -[(1-√5)/2]^n},用 时间复杂度在 O(log n) 和 O(n) 之间,空间复杂度 O(1)
104+
// 经过实际测试,会发现 pow() 系统函数比快速幂慢,说明 pow() 比 O(log n) 慢
105+
// 斐波那契数列是一个自然数的数列,通项公式却是用无理数来表达的。而且当 n 趋向于无穷大时,前一项与后一项的比值越来越逼近黄金分割 0.618(或者说后一项与前一项的比值小数部分越来越逼近 0.618)。
106+
// 斐波那契数列用计算机计算的时候可以直接用四舍五入函数 Round 来计算。
107+
func fib5(N int) int {
108+
var goldenRatio float64 = float64((1 + math.Sqrt(5)) / 2)
109+
return int(math.Round(math.Pow(goldenRatio, float64(N)) / math.Sqrt(5)))
110+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package leetcode
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
)
7+
8+
type question509 struct {
9+
para509
10+
ans509
11+
}
12+
13+
// para 是参数
14+
// one 代表第一个参数
15+
type para509 struct {
16+
one int
17+
}
18+
19+
// ans 是答案
20+
// one 代表第一个答案
21+
type ans509 struct {
22+
one int
23+
}
24+
25+
func Test_Problem509(t *testing.T) {
26+
27+
qs := []question509{
28+
29+
question509{
30+
para509{1},
31+
ans509{1},
32+
},
33+
34+
question509{
35+
para509{2},
36+
ans509{1},
37+
},
38+
39+
question509{
40+
para509{3},
41+
ans509{2},
42+
},
43+
// 如需多个测试,可以复制上方元素。
44+
}
45+
46+
fmt.Printf("------------------------Leetcode Problem 509------------------------\n")
47+
48+
for _, q := range qs {
49+
_, p := q.ans509, q.para509
50+
fmt.Printf("【input】:%v 【output】:%v\n", p, fib(p.one))
51+
}
52+
fmt.Printf("\n\n\n")
53+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# 509. Fibonacci Number
2+
3+
Created Time: Aug 24, 2019 2:52 PM
4+
Difficulty: Easy
5+
Link: https://leetcode.com/problems/fibonacci-number/
6+
Tags: Array,Dynamic Programming,Math,Recursive
7+
8+
## 题目:
9+
10+
The **Fibonacci numbers**, commonly denoted `F(n)` form a sequence, called the **Fibonacci sequence**, such that each number is the sum of the two preceding ones, starting from `0` and `1`. That is,
11+
12+
F(0) = 0,   F(1) = 1
13+
F(N) = F(N - 1) + F(N - 2), for N > 1.
14+
15+
Given `N`, calculate `F(N)`.
16+
17+
**Example 1:**
18+
19+
Input: 2
20+
Output: 1
21+
Explanation: F(2) = F(1) + F(0) = 1 + 0 = 1.
22+
23+
**Example 2:**
24+
25+
Input: 3
26+
Output: 2
27+
Explanation: F(3) = F(2) + F(1) = 1 + 1 = 2.
28+
29+
**Example 3:**
30+
31+
Input: 4
32+
Output: 3
33+
Explanation: F(4) = F(3) + F(2) = 2 + 1 = 3.
34+
35+
**Note:**
36+
37+
0 ≤ `N` ≤ 30.
38+
39+
40+
## 题目大意
41+
42+
斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
43+
44+
```
45+
F(0) = 0, F(1) = 1
46+
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
47+
```
48+
49+
给定 N,计算 F(N)。
50+
51+
提示:0 ≤ N ≤ 30
52+
53+
## 解题思路
54+
55+
56+
- 求斐波那契数列
57+
- 这一题解法很多,大的分类是四种,递归,记忆化搜索(dp),矩阵快速幂,通项公式。其中记忆化搜索可以写 3 种方法,自底向上的,自顶向下的,优化空间复杂度版的。通项公式方法实质是求 a^b 这个还可以用快速幂优化时间复杂度到 O(log n) 。

0 commit comments

Comments
 (0)