From f29352fa2760bd04bf6b4dcf53a626d92bd2833f Mon Sep 17 00:00:00 2001 From: programmercarl <826123027@qq.com> Date: Fri, 4 Nov 2022 12:05:26 +0800 Subject: [PATCH] Update --- problems/0037.解数独.md | 22 ++- problems/0040.组合总和II.md | 8 + problems/0047.全排列II.md | 2 +- problems/0062.不同路径.md | 2 +- problems/0070.爬楼梯.md | 4 + problems/0070.爬楼梯完全背包版本.md | 11 +- problems/0101.对称二叉树.md | 2 +- problems/0102.二叉树的层序遍历.md | 20 -- problems/0150.逆波兰表达式求值.md | 4 - problems/0242.有效的字母异位词.md | 2 +- problems/0279.完全平方数.md | 4 +- problems/0322.零钱兑换.md | 3 +- problems/0509.斐波那契数.md | 3 + problems/0746.使用最小花费爬楼梯.md | 190 +++++++++---------- problems/前序/vim.md | 7 +- problems/贪心算法总结篇.md | 3 + 16 files changed, 142 insertions(+), 145 deletions(-) diff --git a/problems/0037.解数独.md b/problems/0037.解数独.md index f1f621ed..fc1e3114 100644 --- a/problems/0037.解数独.md +++ b/problems/0037.解数独.md @@ -44,7 +44,7 @@ [N皇后问题](https://programmercarl.com/0051.N皇后.html)是因为每一行每一列只放一个皇后,只需要一层for循环遍历一行,递归来来遍历列,然后一行一列确定皇后的唯一位置。 -本题就不一样了,**本题中棋盘的每一个位置都要放一个数字,并检查数字是否合法,解数独的树形结构要比N皇后更宽更深**。 +本题就不一样了,**本题中棋盘的每一个位置都要放一个数字(而N换后是一行只放一个皇后),并检查数字是否合法,解数独的树形结构要比N皇后更宽更深**。 因为这个树形结构太大了,我抽取一部分,如图所示: @@ -57,7 +57,7 @@ **递归函数的返回值需要是bool类型,为什么呢?** -因为解数独找到一个符合的条件(就在树的叶子节点上)立刻就返回,相当于找从根节点到叶子节点一条唯一路径,所以需要使用bool返回值,这一点在[回溯算法:N皇后问题](https://programmercarl.com/0051.N皇后.html)中已经介绍过了,一样的道理。 +因为解数独找到一个符合的条件(就在树的叶子节点上)立刻就返回,相当于找从根节点到叶子节点一条唯一路径,所以需要使用bool返回值。 代码如下: @@ -157,15 +157,16 @@ private: bool backtracking(vector>& board) { for (int i = 0; i < board.size(); i++) { // 遍历行 for (int j = 0; j < board[0].size(); j++) { // 遍历列 - if (board[i][j] != '.') continue; - for (char k = '1'; k <= '9'; k++) { // (i, j) 这个位置放k是否合适 - if (isValid(i, j, k, board)) { - board[i][j] = k; // 放置k - if (backtracking(board)) return true; // 如果找到合适一组立刻返回 - board[i][j] = '.'; // 回溯,撤销k + if (board[i][j] == '.') { + for (char k = '1'; k <= '9'; k++) { // (i, j) 这个位置放k是否合适 + if (isValid(i, j, k, board)) { + board[i][j] = k; // 放置k + if (backtracking(board)) return true; // 如果找到合适一组立刻返回 + board[i][j] = '.'; // 回溯,撤销k + } } - } - return false; // 9个数都试完了,都不行,那么就返回false + return false; // 9个数都试完了,都不行,那么就返回false + } } } return true; // 遍历完没有返回false,说明找到了合适棋盘位置了 @@ -197,6 +198,7 @@ public: backtracking(board); } }; + ``` ## 总结 diff --git a/problems/0040.组合总和II.md b/problems/0040.组合总和II.md index 46b33c89..fcfc396b 100644 --- a/problems/0040.组合总和II.md +++ b/problems/0040.组合总和II.md @@ -131,8 +131,16 @@ if (sum == target) { * used[i - 1] == true,说明同一树枝candidates[i - 1]使用过 * used[i - 1] == false,说明同一树层candidates[i - 1]使用过 +可能有的录友想,为什么 used[i - 1] == false 就是同一树层呢,因为同一树层,used[i - 1] == false 才能表示,当前取的 candidates[i] 是从 candidates[i - 1] 回溯而来的。 + +而 used[i - 1] == true,说明是进入下一层递归,去下一个数,所以是树枝上,如图所示: + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20221021163812.png) + + **这块去重的逻辑很抽象,网上搜的题解基本没有能讲清楚的,如果大家之前思考过这个问题或者刷过这道题目,看到这里一定会感觉通透了很多!** + 那么单层搜索的逻辑代码如下: ```CPP diff --git a/problems/0047.全排列II.md b/problems/0047.全排列II.md index bac30a44..c809c62d 100644 --- a/problems/0047.全排列II.md +++ b/problems/0047.全排列II.md @@ -66,7 +66,7 @@ private: } for (int i = 0; i < nums.size(); i++) { // used[i - 1] == true,说明同一树枝nums[i - 1]使用过 - // used[i - 1] == false,说明同一树层nums[i - 1]使用过 + // used[i - 1] == false,说明同一树层nums[i - 1]使用过 // 如果同一树层nums[i - 1]使用过则直接跳过 if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) { continue; diff --git a/problems/0062.不同路径.md b/problems/0062.不同路径.md index ad5c6f3e..2367587c 100644 --- a/problems/0062.不同路径.md +++ b/problems/0062.不同路径.md @@ -114,7 +114,7 @@ for (int j = 0; j < n; j++) dp[0][j] = 1; 4. 确定遍历顺序 -这里要看一下递归公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。 +这里要看一下递推公式dp[i][j] = dp[i - 1][j] + dp[i][j - 1],dp[i][j]都是从其上方和左方推导而来,那么从左到右一层一层遍历就可以了。 这样就可以保证推导dp[i][j]的时候,dp[i - 1][j] 和 dp[i][j - 1]一定是有数值的。 diff --git a/problems/0070.爬楼梯.md b/problems/0070.爬楼梯.md index 3acc4c11..335ddb23 100644 --- a/problems/0070.爬楼梯.md +++ b/problems/0070.爬楼梯.md @@ -28,6 +28,10 @@ * 1 阶 + 2 阶 * 2 阶 + 1 阶 +# 视频讲解 + +**《代码随想录》算法视频公开课:[带你学透动态规划-爬楼梯|LeetCode:70.爬楼梯)](https://www.bilibili.com/video/BV17h411h7UH),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 + ## 思路 diff --git a/problems/0070.爬楼梯完全背包版本.md b/problems/0070.爬楼梯完全背包版本.md index 4925c312..3093c833 100644 --- a/problems/0070.爬楼梯完全背包版本.md +++ b/problems/0070.爬楼梯完全背包版本.md @@ -3,13 +3,8 @@

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

-# 动态规划:以前我没得选,现在我选择再爬一次! -之前讲这道题目的时候,因为还没有讲背包问题,所以就只是讲了一下爬楼梯最直接的动规方法(斐波那契)。 - -**这次终于讲到了背包问题,我选择带录友们再爬一次楼梯!** - -## 70. 爬楼梯 +# 70. 爬楼梯 [力扣题目链接](https://leetcode.cn/problems/climbing-stairs/) @@ -36,6 +31,10 @@ ## 思路 +之前讲这道题目的时候,因为还没有讲背包问题,所以就只是讲了一下爬楼梯最直接的动规方法(斐波那契)。 + +**这次终于讲到了背包问题,我选择带录友们再爬一次楼梯!** + 这道题目 我们在[动态规划:爬楼梯](https://programmercarl.com/0070.爬楼梯.html) 中已经讲过一次了,原题其实是一道简单动规的题目。 既然这么简单为什么还要讲呢,其实本题稍加改动就是一道面试好题。 diff --git a/problems/0101.对称二叉树.md b/problems/0101.对称二叉树.md index a0870fdd..30ca3d77 100644 --- a/problems/0101.对称二叉树.md +++ b/problems/0101.对称二叉树.md @@ -426,8 +426,8 @@ class Solution: st.append(root.left) st.append(root.right) while st: - leftNode = st.pop() rightNode = st.pop() + leftNode = st.pop() if not leftNode and not rightNode: continue if not leftNode or not rightNode or leftNode.val != rightNode.val: diff --git a/problems/0102.二叉树的层序遍历.md b/problems/0102.二叉树的层序遍历.md index aebb6f08..3a4e0a31 100644 --- a/problems/0102.二叉树的层序遍历.md +++ b/problems/0102.二叉树的层序遍历.md @@ -2073,26 +2073,6 @@ class Solution: if curnode.right: queue.append(curnode.right) return root -# 链表解法 -class Solution: - def connect(self, root: 'Node') -> 'Node': - if not root: - return None - first = root - while first: # 遍历每一层 - dummyHead = Node(None) # 为下一行创建一个虚拟头节点,相当于下一行所有节点链表的头结点(每一层都会创建); - tail = dummyHead # 为下一行维护一个尾节点指针(初始化是虚拟节点) - cur = first - while cur: # 遍历当前层的节点 - if cur.left: # 链接下一行的节点 - tail.next = cur.left - tail = tail.next - if cur.right: - tail.next = cur.right - tail = tail.next - cur = cur.next # cur同层移动到下一节点 - first = dummyHead.next # 此处为换行操作,更新到下一行 - return root ``` JavaScript: ```javascript diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 108c654b..bf90b89b 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -89,12 +89,8 @@ C++代码如下: class Solution { public: int evalRPN(vector& tokens) { -<<<<<<< HEAD - stack st; -======= // 力扣修改了后台测试数据,需要用longlong stack st; ->>>>>>> 28f3b52a82e3cc650290fb02030a53900e122f43 for (int i = 0; i < tokens.size(); i++) { if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/") { long long num1 = st.top(); diff --git a/problems/0242.有效的字母异位词.md b/problems/0242.有效的字母异位词.md index 556bf39a..f8ebc545 100644 --- a/problems/0242.有效的字母异位词.md +++ b/problems/0242.有效的字母异位词.md @@ -361,7 +361,7 @@ C#: ## 相关题目 -* 383.赎金信 +* [383.赎金信](https://programmercarl.com/0383.%E8%B5%8E%E9%87%91%E4%BF%A1.html) * 49.字母异位词分组 * 438.找到字符串中所有字母异位词 diff --git a/problems/0279.完全平方数.md b/problems/0279.完全平方数.md index 7596da12..6acc4891 100644 --- a/problems/0279.完全平方数.md +++ b/problems/0279.完全平方数.md @@ -3,9 +3,9 @@

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

-# 动态规划:一样的套路,再求一次完全平方数 -## 279.完全平方数 + +# 279.完全平方数 [力扣题目链接](https://leetcode.cn/problems/perfect-squares/) diff --git a/problems/0322.零钱兑换.md b/problems/0322.零钱兑换.md index 7f2e6988..e337717f 100644 --- a/problems/0322.零钱兑换.md +++ b/problems/0322.零钱兑换.md @@ -3,9 +3,8 @@

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

-# 动态规划: 给我个机会,我再兑换一次零钱 -## 322. 零钱兑换 +# 322. 零钱兑换 [力扣题目链接](https://leetcode.cn/problems/coin-change/) diff --git a/problems/0509.斐波那契数.md b/problems/0509.斐波那契数.md index d3c58f44..1fa5ca18 100644 --- a/problems/0509.斐波那契数.md +++ b/problems/0509.斐波那契数.md @@ -32,6 +32,9 @@ F(n) = F(n - 1) + F(n - 2),其中 n > 1 * 0 <= n <= 30 +# 视频讲解 + +**《代码随想录》算法视频公开课:[手把手带你入门动态规划 | leetcode:509.斐波那契数](https://www.bilibili.com/video/BV1f5411K7mo),相信结合视频在看本篇题解,更有助于大家对本题的理解**。 ## 思路 diff --git a/problems/0746.使用最小花费爬楼梯.md b/problems/0746.使用最小花费爬楼梯.md index cec6f704..b6f5a734 100644 --- a/problems/0746.使用最小花费爬楼梯.md +++ b/problems/0746.使用最小花费爬楼梯.md @@ -4,10 +4,15 @@

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+ + + # 746. 使用最小花费爬楼梯 [力扣题目链接](https://leetcode.cn/problems/min-cost-climbing-stairs/) +**旧题目描述**: + 数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。 每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。 @@ -30,21 +35,32 @@ * cost 的长度范围是 [2, 1000]。 * cost[i] 将会是一个整型数据,范围为 [0, 999] 。 +----------------- + +本题之前的题目描述是很模糊的,看不出来,第一步需要花费体力值,最后一步不用花费,还是说 第一步不花费体力值,最后一步花费。 + +后来力扣改了题目描述,**新题目描述**: + +给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。 + +你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 + +请你计算并返回达到楼梯顶部的最低花费。 + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20221031170131.png) + + ## 思路 -这道题目可以说是昨天[动态规划:爬楼梯](https://programmercarl.com/0070.爬楼梯.html)的花费版本。 +(**在力扣修改了题目描述下,我又重新修改了题解**) -**注意题目描述:每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯** - -所以示例1中只花费一个15 就可以到阶梯顶,最后一步可以理解为 不用花费。 - -读完题大家应该知道指定需要动态规划的,贪心是不可能了。 +修改之后的题意就比较明确了,题目中说 “你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯” 也就是相当于 跳到 下标 0 或者 下标 1 是不花费体力的, 从 下标 0 下标1 开始跳就要花费体力了。 1. 确定dp数组以及下标的含义 使用动态规划,就要有一个数组来记录状态,本题只需要一个一维数组dp[i]就可以了。 -**dp[i]的定义:到达第i个台阶所花费的最少体力为dp[i]**。(注意这里认为是第一步一定是要花费) +**dp[i]的定义:到达第i台阶所花费的最少体力为dp[i]**。 **对于dp数组的定义,大家一定要清晰!** @@ -52,25 +68,27 @@ **可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]**。 -那么究竟是选dp[i-1]还是dp[i-2]呢? +dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。 -一定是选最小的,所以dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]; +dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。 + +那么究竟是选从dp[i - 1]跳还是从dp[i - 2]跳呢? + +一定是选最小的,所以dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]); -**注意这里为什么是加cost[i],而不是cost[i-1],cost[i-2]之类的**,因为题目中说了:每当你爬上一个阶梯你都要花费对应的体力值 3. dp数组如何初始化 -根据dp数组的定义,dp数组初始化其实是比较难的,因为不可能初始化为第i台阶所花费的最少体力。 +看一下递归公式,dp[i]由dp[i - 1],dp[i - 2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0]dp[1]推出。 -那么看一下递归公式,dp[i]由dp[i-1],dp[i-2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0]dp[1]推出。 +那么 dp[0] 应该是多少呢? 根据dp数组的定义,到达第0台阶所花费的最小体力为dp[0],那么有同学可能想,那dp[0] 应该是 cost[0],例如 cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] 的话,dp[0] 就是 cost[0] 应该是1。 -所以初始化代码为: +这里就要说名了,本题力扣为什么改题意了,而且修改题意之后 就清晰很多的原因了。 + +新题目描述中明确说了 “你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。” 也就是说 从 到达 第 0 个台阶是不花费的,但从 第0 个台阶 往上跳的话,需要花费 cost[0]。 + +所以初始化 dp[0] = 0,dp[1] = 0; -```CPP -vector dp(cost.size()); -dp[0] = cost[0]; -dp[1] = cost[1]; -``` 4. 确定遍历顺序 @@ -78,11 +96,10 @@ dp[1] = cost[1]; 本题的遍历顺序其实比较简单,简单到很多同学都忽略了思考这一步直接就把代码写出来了。 -因为是模拟台阶,而且dp[i]又dp[i-1]dp[i-2]推出,所以是从前到后遍历cost数组就可以了。 +因为是模拟台阶,而且dp[i]由dp[i-1]dp[i-2]推出,所以是从前到后遍历cost数组就可以了。 -**但是稍稍有点难度的动态规划,其遍历顺序并不容易确定下来**。 - -例如:01背包,都知道两个for循环,一个for遍历物品嵌套一个for遍历背包容量,那么为什么不是一个for遍历背包容量嵌套一个for遍历物品呢? 以及在使用一维dp数组的时候遍历背包容量为什么要倒序呢? +> **但是稍稍有点难度的动态规划,其遍历顺序并不容易确定下来**。 +> 例如:01背包,都知道两个for循环,一个for遍历物品嵌套一个for遍历背包容量,那么为什么不是一个for遍历背包容量嵌套一个for遍历物品呢? 以及在使用一维dp数组的时候遍历背包容量为什么要倒序呢? **这些都是遍历顺序息息相关。当然背包问题后续「代码随想录」都会重点讲解的!** @@ -90,79 +107,12 @@ dp[1] = cost[1]; 拿示例2:cost = [1, 100, 1, 1, 1, 100, 1, 1, 100, 1] ,来模拟一下dp数组的状态变化,如下: -![746.使用最小花费爬楼梯](https://img-blog.csdnimg.cn/2021010621363669.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20221026175104.png) 如果大家代码写出来有问题,就把dp数组打印出来,看看和如上推导的是不是一样的。 以上分析完毕,整体C++代码如下: -```CPP -// 版本一 -class Solution { -public: - int minCostClimbingStairs(vector& cost) { - vector dp(cost.size()); - dp[0] = cost[0]; - dp[1] = cost[1]; - for (int i = 2; i < cost.size(); i++) { - dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]; - } - // 注意最后一步可以理解为不用花费,所以取倒数第一步,第二步的最少值 - return min(dp[cost.size() - 1], dp[cost.size() - 2]); - } -}; -``` - -* 时间复杂度:O(n) -* 空间复杂度:O(n) - -还可以优化空间复杂度,因为dp[i]就是由前两位推出来的,那么也不用dp数组了,C++代码如下: - -```CPP -// 版本二 -class Solution { -public: - int minCostClimbingStairs(vector& cost) { - int dp0 = cost[0]; - int dp1 = cost[1]; - for (int i = 2; i < cost.size(); i++) { - int dpi = min(dp0, dp1) + cost[i]; - dp0 = dp1; // 记录一下前两位 - dp1 = dpi; - } - return min(dp0, dp1); - } -}; - -``` - -* 时间复杂度:O(n) -* 空间复杂度:O(1) - -**当然我不建议这么写,能写出版本一就可以了,直观简洁!** - -在后序的讲解中,可能我会忽略这种版本二的写法,大家只要知道有这么个写法就可以了哈。 - -## 拓展 - -这道题描述也确实有点魔幻。 - -题目描述为:每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。 - -示例1: - -输入:cost = [10, 15, 20] -输出:15 - - -**从题目描述可以看出:要不是第一步不需要花费体力,要不就是第最后一步不需要花费体力,我个人理解:题意说的其实是第一步是要支付费用的!**。因为是当你爬上一个台阶就要花费对应的体力值! - -所以我定义的dp[i]意思是也是第一步是要花费体力的,最后一步不用花费体力了,因为已经支付了。 - -当然也可以样,定义dp[i]为:第一步是不花费体力,最后一步是花费体力的。 - -所以代码这么写: - ```CPP class Solution { public: @@ -177,9 +127,58 @@ public: } }; ``` +* 时间复杂度:O(n) +* 空间复杂度:O(n) -这么写看上去比较顺,但是就是感觉和题目描述的不太符。哈哈,也没有必要这么细扣题意了,大家只要知道,题目的意思反正就是要不是第一步不花费,要不是最后一步不花费,都可以。 +还可以优化空间复杂度,因为dp[i]就是由前两位推出来的,那么也不用dp数组了,C++代码如下: +```CPP +// 版本二 +class Solution { +public: + int minCostClimbingStairs(vector& cost) { + int dp0 = 0; + int dp1 = 0; + for (int i = 2; i <= cost.size(); i++) { + int dpi = min(dp1 + cost[i - 1], dp0 + cost[i - 2]); + dp0 = dp1; // 记录一下前两位 + dp1 = dpi; + } + return dp1; + } +}; + +``` + +* 时间复杂度:O(n) +* 空间复杂度:O(1) + +当然如果在面试中,能写出版本一就行,除非面试官额外要求 空间复杂度,那么再去思考版本二,因为版本二还是有点绕。版本一才是正常思路。 + + +## 拓展 + +旧力扣描述,如果按照 第一步是花费的,最后一步不花费,那么代码是这么写的,提交也可以通过 + + +```CPP +// 版本一 +class Solution { +public: + int minCostClimbingStairs(vector& cost) { + vector dp(cost.size()); + dp[0] = cost[0]; // 第一步有花费 + dp[1] = cost[1]; + for (int i = 2; i < cost.size(); i++) { + dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]; + } + // 注意最后一步可以理解为不用花费,所以取倒数第一步,第二步的最少值 + return min(dp[cost.size() - 1], dp[cost.size() - 2]); + } +}; +``` + +当然如果对 动态规划 理解不够深入的话,拓展内容就别看了,容易越看越懵。 ## 总结 @@ -193,17 +192,18 @@ public: 但我也可以随便选来一道难题讲呗,这其实是最省事的,不用管什么题目顺序,看心情找一道就讲。 -难的是把题目按梯度排好,循序渐进,再按照统一方法论把这些都串起来,哈哈,所以大家不要催我哈,按照我的节奏一步一步来就行啦。 +难的是把题目按梯度排好,循序渐进,再按照统一方法论把这些都串起来,所以大家不要催我哈,按照我的节奏一步一步来就行了。 学算法,认准「代码随想录」,没毛病! -## 其他语言版本 +## 其他语言版本 +以下版本其他语言版本,大多是按照旧力扣题解来写的,欢迎大家在[Github](https://github.com/youngyangyang04/leetcode-master)上[提交pr](https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A),修正一波。 ### Java ```Java -// 方式一:第一步支付费用 +// 方式一:第一步不支付费用 class Solution { public int minCostClimbingStairs(int[] cost) { int len = cost.length; @@ -224,7 +224,7 @@ class Solution { ``` ```Java -// 方式二:第一步不支付费用 +// 方式二:第一步支付费用 class Solution { public int minCostClimbingStairs(int[] cost) { int[] dp = new int[cost.length]; diff --git a/problems/前序/vim.md b/problems/前序/vim.md index c49ff1e3..ce4a0139 100644 --- a/problems/前序/vim.md +++ b/problems/前序/vim.md @@ -1,4 +1,6 @@ -# 人生苦短,我用VIM! +# 人生苦短,我用VIM!| 最强vim配置 + +> Github地址:[https://github.com/youngyangyang04/PowerVim](https://github.com/youngyangyang04/PowerVim) 熟悉我的录友,应该都知道我是vim流,无论是写代码还是写文档(Markdown),都是vim,都没用IDE。 @@ -53,7 +55,7 @@ IDE那么很吃内存,打开个IDE卡半天,用VIM就很轻便了,秒开 |_| \___/ \_/\_/ \___|_| \/ |_|_| |_| |_| ``` -这个配置我开源在Github上,地址:https://github.com/youngyangyang04/PowerVim +这个配置我开源在Github上,地址:[https://github.com/youngyangyang04/PowerVim](https://github.com/youngyangyang04/PowerVim) @@ -92,6 +94,7 @@ sh install.sh ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211013102249.png) +Github地址:[https://github.com/youngyangyang04/PowerVim](https://github.com/youngyangyang04/PowerVim) 最后,因为这个vim配置因为我一直没有宣传,所以star数量很少,哈哈哈,录友们去给个star吧,真正的开发利器,值得顶起来! diff --git a/problems/贪心算法总结篇.md b/problems/贪心算法总结篇.md index 86cd053f..d70eecaa 100644 --- a/problems/贪心算法总结篇.md +++ b/problems/贪心算法总结篇.md @@ -4,6 +4,9 @@

参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+# 贪心算法总结篇 + + 我刚刚开始讲解贪心系列的时候就说了,贪心系列并不打算严格的从简单到困难这么个顺序来讲解。 因为贪心的简单题可能往往过于简单甚至感觉不到贪心,如果我连续几天讲解简单的贪心,估计录友们一定会不耐烦了,会感觉贪心有啥好学的。