diff --git a/notes/剑指 offer 题解.md b/notes/剑指 offer 题解.md index bb7dc781..8af879a1 100644 --- a/notes/剑指 offer 题解.md +++ b/notes/剑指 offer 题解.md @@ -410,18 +410,48 @@ public int pop() throws Exception { ## 题目描述 -以 O(1) 的时间复杂度求菲波那切数列。 +求菲波那契数列的第 n 项。

## 解题思路 -如果使用递归求解,那么会重复计算一些子问题。例如,求 f(10) 需要计算 f(9) 和 f(8),计算 f(9) 需要计算 f(8) 和 f(7),可以看到 f(8) 被重复计算了。 +如果使用递归求解,会重复计算一些子问题。例如,计算 f(10) 需要计算 f(9) 和 f(8),计算 f(9) 需要计算 f(8) 和 f(7),可以看到 f(8) 被重复计算了。

递归方法是将一个问题划分成多个子问题求解,动态规划也是如此,但是动态规划会把子问题的解缓存起来,避免重复求解子问题。 +```java +public int Fibonacci(int n) { + if(n <= 1) return n; + int[] fib = new int[n + 1]; + fib[1] = 1; + for (int i = 2; i <= n; i++) { + fib[i] = fib[i - 1] + fib[i - 2]; + } + return fib[n]; +} +``` + +考虑到第 i 项只与第 i-1 和第 i-2 项有关,因此只需要存储前两项的值就能求解第 i 项,从而将空间复杂度由 O(N) 降低为 O(1)。 + +```java +public int Fibonacci(int n) { + if(n <= 1) return n; + int pre2 = 0, pre1 = 1; + int fib = 0; + for (int i = 2; i <= n; i++) { + fib = pre2 + pre1; + pre2 = pre1; + pre1 = fib; + } + return fib; +} +``` + +由于待求解的 n 小于 40,因此可以将前 40 项的结果先进行计算,之后就能以 O(1) 时间复杂度得到第 n 项的值了。 + ```java public class Solution { private int[] fib = new int[40]; @@ -446,6 +476,8 @@ public class Solution { ## 解题思路 +复杂度:O(N) + O(N) + ```java public int JumpFloor(int n) { if (n == 1) return 1; @@ -459,6 +491,22 @@ public int JumpFloor(int n) { } ``` +复杂度:O(N) + O(1) + +```java +public int JumpFloor(int n) { + if (n <= 1) return n; + int pre2 = 0, pre1 = 1; + int result = 0; + for (int i = 1; i <= n; i++) { + result = pre2 + pre1; + pre2 = pre1; + pre1 = result; + } + return result; +} +``` + # 10.3 变态跳台阶 ## 题目描述 @@ -488,9 +536,11 @@ public int JumpFloorII(int n) { ## 解题思路 +复杂度:O(N) + O(N) + ```java public int RectCover(int n) { - if (n < 2) return n; + if (n <= 2) return n; int[] dp = new int[n]; dp[0] = 1; dp[1] = 2; @@ -501,6 +551,22 @@ public int RectCover(int n) { } ``` +复杂度:O(N) + O(1) + +```java +public int RectCover(int n) { + if (n <= 2) return n; + int pre2 = 1, pre1 = 2; + int result = 0; + for (int i = 3; i <= n; i++) { + result = pre2 + pre1; + pre2 = pre1; + pre1 = result; + } + return result; +} +``` + # 11. 旋转数组的最小数字 ## 题目描述