From dbae8d1b3f5a11201876c6da853e01336d326414 Mon Sep 17 00:00:00 2001 From: AC_Oier Date: Sat, 4 Sep 2021 09:45:07 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8feat:=20Add=20=E5=89=91=E6=8C=87=20Off?= =?UTF-8?q?er=2010-=20I?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "Index/\346\211\223\350\241\250.md" | 1 + ...65\345\277\253\351\200\237\345\271\202.md" | 1 + "Index/\347\272\277\346\200\247 DP.md" | 1 + ...06\345\214\226\346\220\234\347\264\242.md" | 1 + ...10\347\256\200\345\215\225\357\274\211.md" | 266 ++++++++++++++++++ 5 files changed, 270 insertions(+) create mode 100644 "LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 10- I. \346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227\357\274\210\347\256\200\345\215\225\357\274\211.md" diff --git "a/Index/\346\211\223\350\241\250.md" "b/Index/\346\211\223\350\241\250.md" index 9da184a8..a286eaac 100644 --- "a/Index/\346\211\223\350\241\250.md" +++ "b/Index/\346\211\223\350\241\250.md" @@ -3,5 +3,6 @@ | [401. 二进制手表](https://leetcode-cn.com/problems/binary-watch/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/binary-watch/solution/gong-shui-san-xie-jian-dan-ti-xue-da-bia-gwn2/) | 简单 | 🤩🤩🤩🤩🤩 | | [1137. 第 N 个泰波那契数](https://leetcode-cn.com/problems/n-th-tribonacci-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/n-th-tribonacci-number/solution/gong-shui-san-xie-yi-ti-si-jie-die-dai-d-m1ie/) | 简单 | 🤩🤩🤩🤩 | | [1646. 获取生成数组中的最大值](https://leetcode-cn.com/problems/get-maximum-in-generated-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/get-maximum-in-generated-array/solution/gong-shui-san-xie-jian-dan-mo-ni-ti-by-a-sj53/) | 简单 | 🤩🤩🤩🤩 | +| [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-dong-tai-9zip0/) | 简单 | 🤩🤩🤩🤩🤩 | | [面试题 10.02. 变位词组](https://leetcode-cn.com/problems/group-anagrams-lcci/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/group-anagrams-lcci/solution/gong-shui-san-xie-tong-ji-bian-wei-ci-de-0iqe/) | 中等 | 🤩🤩🤩🤩 | diff --git "a/Index/\347\237\251\351\230\265\345\277\253\351\200\237\345\271\202.md" "b/Index/\347\237\251\351\230\265\345\277\253\351\200\237\345\271\202.md" index df2da683..4ddd66ea 100644 --- "a/Index/\347\237\251\351\230\265\345\277\253\351\200\237\345\271\202.md" +++ "b/Index/\347\237\251\351\230\265\345\277\253\351\200\237\345\271\202.md" @@ -2,4 +2,5 @@ | ------------------------------------------------------------ | ------------------------------------------------------------ | ---- | -------- | | [552. 学生出勤记录 II](https://leetcode-cn.com/problems/student-attendance-record-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/student-attendance-record-ii/solution/gong-shui-san-xie-yi-ti-san-jie-ji-yi-hu-fdfx/) | 困难 | 🤩🤩🤩🤩 | | [1137. 第 N 个泰波那契数](https://leetcode-cn.com/problems/n-th-tribonacci-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/n-th-tribonacci-number/solution/gong-shui-san-xie-yi-ti-si-jie-die-dai-d-m1ie/) | 简单 | 🤩🤩🤩🤩🤩 | +| [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-dong-tai-9zip0/) | 简单 | 🤩🤩🤩🤩🤩 | diff --git "a/Index/\347\272\277\346\200\247 DP.md" "b/Index/\347\272\277\346\200\247 DP.md" index c6d606aa..4fc47928 100644 --- "a/Index/\347\272\277\346\200\247 DP.md" +++ "b/Index/\347\272\277\346\200\247 DP.md" @@ -13,6 +13,7 @@ | [1137. 第 N 个泰波那契数](https://leetcode-cn.com/problems/n-th-tribonacci-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/n-th-tribonacci-number/solution/gong-shui-san-xie-yi-ti-si-jie-die-dai-d-m1ie/) | 简单 | 🤩🤩🤩🤩 | | [1751. 最多可以参加的会议数目 II](https://leetcode-cn.com/problems/maximum-number-of-events-that-can-be-attended-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/maximum-number-of-events-that-can-be-attended-ii/solution/po-su-dp-er-fen-dp-jie-fa-by-ac_oier-88du/) | 困难 | 🤩🤩🤩 | | [1787. 使所有区间的异或结果为零](https://leetcode-cn.com/problems/make-the-xor-of-all-segments-equal-to-zero/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/make-the-xor-of-all-segments-equal-to-zero/solution/gong-shui-san-xie-chou-xiang-cheng-er-we-ww79/) | 困难 | 🤩🤩🤩🤩 | +| [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-dong-tai-9zip0/) | 简单 | 🤩🤩🤩🤩🤩 | | [剑指 Offer 42. 连续子数组的最大和](https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/solution/gong-shui-san-xie-jian-dan-xian-xing-dp-mqk5v/) | 简单 | 🤩🤩🤩🤩🤩 | | [LCP 07. 传递信息](https://leetcode-cn.com/problems/chuan-di-xin-xi/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/chuan-di-xin-xi/solution/gong-shui-san-xie-tu-lun-sou-suo-yu-dong-cyxo/) | 简单 | 🤩🤩🤩🤩 | diff --git "a/Index/\350\256\260\345\277\206\345\214\226\346\220\234\347\264\242.md" "b/Index/\350\256\260\345\277\206\345\214\226\346\220\234\347\264\242.md" index 791bc319..db5d018f 100644 --- "a/Index/\350\256\260\345\277\206\345\214\226\346\220\234\347\264\242.md" +++ "b/Index/\350\256\260\345\277\206\345\214\226\346\220\234\347\264\242.md" @@ -6,4 +6,5 @@ | [552. 学生出勤记录 II](https://leetcode-cn.com/problems/student-attendance-record-ii/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/student-attendance-record-ii/solution/gong-shui-san-xie-yi-ti-san-jie-ji-yi-hu-fdfx/) | 困难 | 🤩🤩🤩🤩 | | [576. 出界的路径数](https://leetcode-cn.com/problems/out-of-boundary-paths/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/out-of-boundary-paths/solution/gong-shui-san-xie-yi-ti-shuang-jie-ji-yi-asrz/) | 中等 | 🤩🤩🤩🤩 | | [1137. 第 N 个泰波那契数](https://leetcode-cn.com/problems/n-th-tribonacci-number/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/n-th-tribonacci-number/solution/gong-shui-san-xie-yi-ti-si-jie-die-dai-d-m1ie/) | 简单 | 🤩🤩🤩🤩 | +| [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-dong-tai-9zip0/) | 简单 | 🤩🤩🤩🤩🤩 | diff --git "a/LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 10- I. \346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227\357\274\210\347\256\200\345\215\225\357\274\211.md" "b/LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 10- I. \346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227\357\274\210\347\256\200\345\215\225\357\274\211.md" new file mode 100644 index 00000000..11c0a6db --- /dev/null +++ "b/LeetCode/\345\211\221\346\214\207 Offer/\345\211\221\346\214\207 Offer 10- I. \346\226\220\346\263\242\351\202\243\345\245\221\346\225\260\345\210\227\357\274\210\347\256\200\345\215\225\357\274\211.md" @@ -0,0 +1,266 @@ +### 题目描述 + +这是 LeetCode 上的 **[剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/solution/gong-shui-san-xie-yi-ti-si-jie-dong-tai-9zip0/)** ,难度为 **简单**。 + +Tag : 「动态规划」、「线性 DP」、「记忆化搜索」、「打表」、「矩阵快速幂」 + + + +写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下: + +* F(0) = 0,   F(1) = 1 +* F(N) = F(N - 1) + F(N - 2), 其中 N > 1. + +斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。 + +答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 + +示例 1: +``` +输入:n = 2 + +输出:1 +``` +示例 2: +``` +输入:n = 5 + +输出:5 +``` + +提示: +* 0 <= n <= 100 + +--- + +### 递推实现动态规划 + +既然转移方程都给出了,直接根据转移方程从头到尾递递推一遍即可。 + +代码: +```Java +class Solution { + int mod = (int)1e9+7; + public int fib(int n) { + if (n <= 1) return n; + int a = 0, b = 1; + for (int i = 2; i <= n; i++) { + int c = a + b; + c %= mod; + a = b; + b = c; + } + return b; + } +} +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(1)$ + +--- + +### 递归实现动态规划 + +能以「递推」形式实现动态规划,自然也能以「递归」的形式实现。 + +为防止重复计算,我们需要加入「记忆化搜索」功能,同时利用某个值 $x$ 在不同的样例之间可能会作为“中间结果”被重复计算,并且计算结果 $fib(x)$ 固定,我们可以使用 `static` 修饰缓存器,以实现计算过的结果在所有测试样例中共享。 + +代码: +```Java +class Solution { + static int mod = (int)1e9+7; + static int N = 110; + static int[] cache = new int[N]; + public int fib(int n) { + if (n <= 1) return n; + if (cache[n] != 0) return cache[n]; + cache[n] = fib(n - 1) + fib(n - 2); + cache[n] %= mod; + return cache[n]; + } +} +``` +* 时间复杂度:$O(n)$ +* 空间复杂度:$O(1)$ + +--- + +### 打表 + +经过「解法二」,我们进一步发现,可以利用数据范围只有 $100$ 进行打表预处理,然后直接返回。 + +代码: +```Java +class Solution { + static int mod = (int)1e9+7; + static int N = 110; + static int[] cache = new int[N]; + static { + cache[1] = 1; + for (int i = 2; i < N; i++) { + cache[i] = cache[i - 1] + cache[i - 2]; + cache[i] %= mod; + } + } + public int fib(int n) { + return cache[n]; + } +} +``` +* 时间复杂度:将打表逻辑放到本地执行,复杂度为 $O(1)$;否则为 $O(C)$,$C$ 为常量,固定为 $110$ +* 空间复杂度:$O(C)$ + +--- + +### 矩阵快速幂 + +**对于数列递推问题,可以使用矩阵快速幂进行加速,最完整的介绍在 [这里](https://mp.weixin.qq.com/s?__biz=MzU4NDE3MTEyMA==&mid=2247488198&idx=1&sn=8272ca6b0ef6530413da4a270abb68bc&chksm=fd9cb9d9caeb30cf6c2defab0f5204adc158969d64418916e306f6bf50ae0c38518d4e4ba146&token=1067450240&lang=zh_CN#rd) 讲过。** + +对于本题,某个 $f(n)$ 依赖于 $f(n - 1)$ 和 $f(n - 2)$,将其依赖的状态存成列向量: + +$$ +\begin{bmatrix} +f(n - 1)\\ +f(n - 2) +\end{bmatrix} +$$ + +目标值 $f(n)$ 所在矩阵为: + +$$ +\begin{bmatrix} +f(n)\\ +f(n - 1) +\end{bmatrix} +$$ + +根据矩阵乘法,不难发现: + +$$ +\begin{bmatrix} +f(n)\\ +f(n - 1) +\end{bmatrix} + += + +\begin{bmatrix} +1, 1\\ +1, 0 +\end{bmatrix} + +* + +\begin{bmatrix} +f(n - 1)\\ +f(n - 2) +\end{bmatrix} +$$ + +我们令: + +$$ +mat = +\begin{bmatrix} +1, 1\\ +1, 0 +\end{bmatrix} +$$ + +起始时,我们只有 $ +\begin{bmatrix} +f(1)\\ +f(0) +\end{bmatrix} +$,根据递推式得: + +$$ +\begin{bmatrix} +f(n)\\ +f(n - 1) +\end{bmatrix} + += + +mat * mat * ... * mat * + +\begin{bmatrix} +f(1)\\ +f(0) +\end{bmatrix} +$$ + +再根据矩阵乘法具有「结合律」,最终可得: + +$$ +\begin{bmatrix} +f(n)\\ +f(n - 1) +\end{bmatrix} + += + +mat^{n - 1} + +* + +\begin{bmatrix} +f(1)\\ +f(0) +\end{bmatrix} +$$ + +计算 $mat^{n - 1}$ 可以套用「快速幂」进行求解。 + +代码: +```Java +class Solution { + int mod = (int)1e9+7; + long[][] mul(long[][] a, long[][] b) { + int r = a.length, c = b[0].length, z = b.length; + long[][] ans = new long[r][c]; + for (int i = 0; i < r; i++) { + for (int j = 0; j < c; j++) { + for (int k = 0; k < z; k++) { + ans[i][j] += a[i][k] * b[k][j]; + ans[i][j] %= mod; + } + } + } + return ans; + } + public int fib(int n) { + if (n <= 1) return n; + long[][] mat = new long[][]{ + {1, 1}, + {1, 0} + }; + long[][] ans = new long[][]{ + {1}, + {0} + }; + int x = n - 1; + while (x != 0) { + if ((x & 1) != 0) ans = mul(mat, ans); + mat = mul(mat, mat); + x >>= 1; + } + return (int)(ans[0][0] % mod); + } +} +``` +* 时间复杂度:$O(\log{n})$ +* 空间复杂度:$O(1)$ + +--- + +### 最后 + +这是我们「刷穿 LeetCode」系列文章的第 `剑指 Offer 10- I` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。 + +在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。 + +为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode 。 + +在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。 +