diff --git a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md index d70dcba5..f8299ea8 100644 --- a/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md +++ b/problems/0034.在排序数组中查找元素的第一个和最后一个位置.md @@ -29,7 +29,7 @@ * 输出:[-1,-1] -# 思路 +## 思路 这道题目如果基础不是很好,不建议大家看简短的代码,简短的代码隐藏了太多逻辑,结果就是稀里糊涂把题AC了,但是没有想清楚具体细节! @@ -54,7 +54,7 @@ **刚刚接触二分搜索的同学不建议上来就像如果用一个二分来查找左右边界,很容易把自己绕进去,建议扎扎实实的写两个二分分别找左边界和右边界** -## 寻找右边界 +### 寻找右边界 先来寻找右边界,至于二分查找,如果看过[704.二分查找](https://programmercarl.com/0704.二分查找.html)就会知道,二分查找中什么时候用while (left <= right),有什么时候用while (left < right),其实只要清楚**循环不变量**,很容易区分两种写法。 @@ -84,7 +84,7 @@ int getRightBorder(vector& nums, int target) { } ``` -## 寻找左边界 +### 寻找左边界 ```CPP // 二分查找,寻找target的左边界leftBorder(不包括target) @@ -106,7 +106,7 @@ int getLeftBorder(vector& nums, int target) { } ``` -## 处理三种情况 +### 处理三种情况 左右边界计算完之后,看一下主体代码,这里把上面讨论的三种情况,都覆盖了 @@ -161,16 +161,16 @@ private: 但拆开更清晰一些,而且把三种情况以及对应的处理逻辑完整的展现出来了。 -# 总结 +## 总结 初学者建议大家一块一块的去分拆这道题目,正如本题解描述,想清楚三种情况之后,先专注于寻找右区间,然后专注于寻找左区间,左右根据左右区间做最后判断。 不要上来就想如果一起寻找左右区间,搞着搞着就会顾此失彼,绕进去拔不出来了。 -# 其他语言版本 +## 其他语言版本 -## Java +### Java ```java class Solution { @@ -272,7 +272,7 @@ class Solution { -## Python +### Python ```python class Solution: @@ -388,12 +388,12 @@ class Solution: return [leftBorder, rightBorder] ``` -## Go +### Go ```go ``` -## JavaScript +### JavaScript ```js var searchRange = function(nums, target) { diff --git a/problems/0046.全排列.md b/problems/0046.全排列.md index 2743a667..7c9a8549 100644 --- a/problems/0046.全排列.md +++ b/problems/0046.全排列.md @@ -40,7 +40,7 @@ 我以[1,2,3]为例,抽象成树形结构如下: -![46.全排列](https://img-blog.csdnimg.cn/20201209174225145.png) +![46.全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20211027181706.png) ### 回溯三部曲 @@ -52,7 +52,7 @@ 但排列问题需要一个used数组,标记已经选择的元素,如图橘黄色部分所示: -![46.全排列](https://img-blog.csdnimg.cn/20201209174225145.png) +![46.全排列](https://code-thinking-1253855093.file.myqcloud.com/pics/20211027181706.png) 代码如下: diff --git a/problems/0141.环形链表.md b/problems/0141.环形链表.md index 559ded41..dec066cf 100644 --- a/problems/0141.环形链表.md +++ b/problems/0141.环形链表.md @@ -17,7 +17,7 @@ ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210727173600.png) -# 思路 +## 思路 可以使用快慢指针法, 分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。 @@ -62,16 +62,15 @@ public: }; ``` -# 扩展 +## 扩展 -做完这道题目,可以在做做142.环形链表II,不仅仅要找环,还要找环的入口。 - -142.环形链表II题解:[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html) +做完这道题目,可以在做做[142.环形链表II](https://mp.weixin.qq.com/s/gt_VH3hQTqNxyWcl1ECSbQ),不仅仅要找环,还要找环的入口。 -# 其他语言版本 -## Java +## 其他语言版本 + +### Java ```java public class Solution { @@ -91,7 +90,7 @@ public class Solution { } ``` -## Python +### Python ```python class Solution: @@ -111,7 +110,7 @@ class Solution: ```go ``` -## JavaScript +### JavaScript ```js var hasCycle = function(head) { diff --git a/problems/0143.重排链表.md b/problems/0143.重排链表.md index a6412d2e..f072ec8f 100644 --- a/problems/0143.重排链表.md +++ b/problems/0143.重排链表.md @@ -10,7 +10,7 @@ ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210726160122.png) -# 思路 +## 思路 本篇将给出三种C++实现的方法 @@ -18,7 +18,7 @@ * 双向队列模拟 * 直接分割链表 -## 方法一 +### 方法一 把链表放进数组中,然后通过双指针法,一前一后,来遍历数组,构造链表。 @@ -55,7 +55,7 @@ public: }; ``` -## 方法二 +### 方法二 把链表放进双向队列,然后通过双向队列一前一后弹出数据,来构造新的链表。这种方法比操作数组容易一些,不用双指针模拟一前一后了 @@ -92,7 +92,7 @@ public: }; ``` -## 方法三 +### 方法三 将链表分割成两个链表,然后把第二个链表反转,之后在通过两个链表拼接成新的链表。 @@ -168,54 +168,11 @@ public: }; ``` -# 其他语言版本 +## 其他语言版本 -Java: +### Java ```java -// 方法三 -public class ReorderList { - public void reorderList(ListNode head) { - ListNode fast = head, slow = head; - //求出中点 - while (fast.next != null && fast.next.next != null) { - slow = slow.next; - fast = fast.next.next; - } - //right就是右半部分 12345 就是45 1234 就是34 - ListNode right = slow.next; - //断开左部分和右部分 - slow.next = null; - //反转右部分 right就是反转后右部分的起点 - right = reverseList(right); - //左部分的起点 - ListNode left = head; - //进行左右部分来回连接 - //这里左部分的节点个数一定大于等于右部分的节点个数 因此只判断right即可 - while (right != null) { - ListNode curLeft = left.next; - left.next = right; - left = curLeft; - - ListNode curRight = right.next; - right.next = left; - right = curRight; - } - } - - public ListNode reverseList(ListNode head) { - ListNode headNode = new ListNode(0); - ListNode cur = head; - ListNode next = null; - while (cur != null) { - next = cur.next; - cur.next = headNode.next; - headNode.next = cur; - cur = next; - } - return headNode.next; - } -} // 方法一 Java实现,使用数组存储节点 class Solution { @@ -278,10 +235,54 @@ class Solution { } } +// 方法三 +public class ReorderList { + public void reorderList(ListNode head) { + ListNode fast = head, slow = head; + //求出中点 + while (fast.next != null && fast.next.next != null) { + slow = slow.next; + fast = fast.next.next; + } + //right就是右半部分 12345 就是45 1234 就是34 + ListNode right = slow.next; + //断开左部分和右部分 + slow.next = null; + //反转右部分 right就是反转后右部分的起点 + right = reverseList(right); + //左部分的起点 + ListNode left = head; + //进行左右部分来回连接 + //这里左部分的节点个数一定大于等于右部分的节点个数 因此只判断right即可 + while (right != null) { + ListNode curLeft = left.next; + left.next = right; + left = curLeft; + + ListNode curRight = right.next; + right.next = left; + right = curRight; + } + } + + public ListNode reverseList(ListNode head) { + ListNode headNode = new ListNode(0); + ListNode cur = head; + ListNode next = null; + while (cur != null) { + next = cur.next; + cur.next = headNode.next; + headNode.next = cur; + cur = next; + } + return headNode.next; + } +} + ``` -Python: -```python3 +### Python +```python # 方法二 双向队列 class Solution: def reorderList(self, head: ListNode) -> None: @@ -336,9 +337,10 @@ class Solution: cur = temp return pre ``` -Go: +### Go + +### JavaScript -JavaScript: ```javascript // 方法一 使用数组存储节点 var reorderList = function(head, s = [], tmp) { diff --git a/problems/0234.回文链表.md b/problems/0234.回文链表.md index db02a6ba..b47718e2 100644 --- a/problems/0234.回文链表.md +++ b/problems/0234.回文链表.md @@ -22,9 +22,9 @@ * 输出: true -# 思路 +## 思路 -## 数组模拟 +### 数组模拟 最直接的想法,就是把链表装成数组,然后再判断是否回文。 @@ -79,7 +79,7 @@ public: ``` -## 反转后半部分链表 +### 反转后半部分链表 分为如下几步: @@ -139,9 +139,9 @@ public: ``` -# 其他语言版本 +## 其他语言版本 -## Java +### Java ```java // 方法一,使用数组 @@ -215,9 +215,9 @@ class Solution { } ``` -## Python +### Python -```python3 +```python #数组模拟 class Solution: def isPalindrome(self, head: ListNode) -> bool: @@ -281,7 +281,7 @@ class Solution: ``` -## JavaScript +### JavaScript ```js var isPalindrome = function(head) { diff --git a/problems/0376.摆动序列.md b/problems/0376.摆动序列.md index 5587a8c7..a5c6f73b 100644 --- a/problems/0376.摆动序列.md +++ b/problems/0376.摆动序列.md @@ -9,7 +9,7 @@ > 本周讲解了[贪心理论基础](https://programmercarl.com/贪心算法理论基础.html),以及第一道贪心的题目:[贪心算法:分发饼干](https://programmercarl.com/0455.分发饼干.html),可能会给大家一种贪心算法比较简单的错觉,好了,接下来几天的题目难度要上来了,哈哈。 -## 376. 摆动序列 +# 376. 摆动序列 [力扣题目链接](https://leetcode-cn.com/problems/wiggle-subsequence/) @@ -20,18 +20,18 @@ 给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。 示例 1: -输入: [1,7,4,9,2,5] -输出: 6 -解释: 整个序列均为摆动序列。 +* 输入: [1,7,4,9,2,5] +* 输出: 6 +* 解释: 整个序列均为摆动序列。 示例 2: -输入: [1,17,5,10,13,15,10,5,16,8] -输出: 7 -解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。 +* 输入: [1,17,5,10,13,15,10,5,16,8] +* 输出: 7 +* 解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。 示例 3: -输入: [1,2,3,4,5,6,7,8,9] -输出: 2 +* 输入: [1,2,3,4,5,6,7,8,9] +* 输出: 2 ## 思路1(贪心解法) @@ -172,7 +172,7 @@ public: ## 其他语言版本 -Java: +### Java ```Java class Solution { public int wiggleMaxLength(int[] nums) { @@ -199,7 +199,7 @@ class Solution { } ``` -Python: +### Python ```python3 class Solution: def wiggleMaxLength(self, nums: List[int]) -> int: @@ -212,7 +212,7 @@ class Solution: return res ``` -Go: +### Go ```golang func wiggleMaxLength(nums []int) int { var count,preDiff,curDiff int @@ -232,7 +232,7 @@ func wiggleMaxLength(nums []int) int { } ``` -Javascript: +### Javascript ```Javascript var wiggleMaxLength = function(nums) { if(nums.length <= 1) return nums.length diff --git a/problems/0455.分发饼干.md b/problems/0455.分发饼干.md index 2dc51265..c992b9a5 100644 --- a/problems/0455.分发饼干.md +++ b/problems/0455.分发饼干.md @@ -7,7 +7,7 @@

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

-## 455.分发饼干 +# 455.分发饼干 [力扣题目链接](https://leetcode-cn.com/problems/assign-cookies/) @@ -16,20 +16,14 @@ 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。 示例 1: -输入: g = [1,2,3], s = [1,1] -输出: 1 -解释: -你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 -虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 -所以你应该输出1。 +* 输入: g = [1,2,3], s = [1,1] +* 输出: 1 +解释:你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。所以你应该输出1。 示例 2: -输入: g = [1,2], s = [1,2,3] -输出: 2 -解释: -你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 -你拥有的饼干数量和尺寸都足以让所有孩子满足。 -所以你应该输出2. +* 输入: g = [1,2], s = [1,2,3] +* 输出: 2 +* 解释:你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。你拥有的饼干数量和尺寸都足以让所有孩子满足。所以你应该输出2. 提示: @@ -114,7 +108,7 @@ public: ## 其他语言版本 -Java: +### Java ```java class Solution { // 思路1:优先考虑饼干,小饼干先喂饱小胃口 @@ -153,7 +147,7 @@ class Solution { } ``` -Python: +### Python ```python3 class Solution: # 思路1:优先考虑胃饼干 @@ -180,7 +174,7 @@ class Solution: return count ``` -Go: +### Go ```golang //排序后,局部最优 func findContentChildren(g []int, s []int) int { @@ -199,7 +193,7 @@ func findContentChildren(g []int, s []int) int { } ``` -Javascript: +### Javascript ```js var findContentChildren = function(g, s) { g = g.sort((a, b) => a - b) @@ -217,7 +211,7 @@ var findContentChildren = function(g, s) { ``` -C: +### C ```c int cmp(int* a, int* b) { return *a - *b; diff --git a/problems/二叉树总结篇.md b/problems/二叉树总结篇.md index 37696fc0..322670e0 100644 --- a/problems/二叉树总结篇.md +++ b/problems/二叉树总结篇.md @@ -150,6 +150,12 @@ 所以求普通二叉树的属性还是要具体问题具体分析。 +二叉树专题汇聚为一张图: + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211030125421.png) + +这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。 + **最后,二叉树系列就这么完美结束了,估计这应该是最长的系列了,感谢大家33天的坚持与陪伴,接下来我们又要开始新的系列了「回溯算法」!** diff --git a/problems/回溯总结.md b/problems/回溯总结.md index 50a61b9e..b12b88e1 100644 --- a/problems/回溯总结.md +++ b/problems/回溯总结.md @@ -432,9 +432,9 @@ N皇后问题分析: 回溯专题汇聚为一张图: -![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211025180652.png) +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211030124742.png) -这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:莫非毛,所画,总结的非常好,分享给大家。 +这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:[莫非毛](https://wx.zsxq.com/dweb2/index/footprint/828844212542),所画,总结的非常好,分享给大家。 **回溯算法系列正式结束,新的系列终将开始,录友们准备开启新的征程!** diff --git a/problems/贪心算法总结篇.md b/problems/贪心算法总结篇.md index 09d22da1..9d506f75 100644 --- a/problems/贪心算法总结篇.md +++ b/problems/贪心算法总结篇.md @@ -126,6 +126,14 @@ Carl个人认为:如果找出局部最优并可以推出全局最优,就是 ## 总结 + +贪心专题汇聚为一张图: + +![](https://code-thinking-1253855093.file.myqcloud.com/pics/20211110121605.png) + +这个图是 [代码随想录知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 成员:[青](https://wx.zsxq.com/dweb2/index/footprint/185251215558842)所画,总结的非常好,分享给大家。 + + 很多没有接触过贪心的同学都会感觉贪心有啥可学的,但只要跟着「代码随想录」坚持下来之后,就会发现,贪心是一种很重要的算法思维而且并不简单,贪心往往妙的出其不意,触不及防! **回想一下我们刚刚开始讲解贪心的时候,大家会发现自己在坚持中进步了很多!**