C:/Program Files/Git/problems/1-40更新链接‘

This commit is contained in:
XuDaHaoRen
2021-08-21 21:21:03 +08:00
parent 391a04bf9f
commit 4e19ab8d00
19 changed files with 80 additions and 80 deletions

View File

@ -10,7 +10,7 @@
# 5.最长回文子串
题目链接:https://leetcode-cn.com/problems/longest-palindromic-substring/
[力扣题目链接](https://leetcode-cn.com/problems/longest-palindromic-substring/)
给你一个字符串 s找到 s 中最长的回文子串。
@ -30,11 +30,11 @@
示例 4
* 输入s = "ac"
* 输出:"a"
 
# 思路
本题和[647.回文子串](https://mp.weixin.qq.com/s/2WetyP6IYQ6VotegepVpEw) 差不多是一样的但647.回文子串更基本一点建议可以先做647.回文子串
本题和[647.回文子串](https://programmercarl.com/0647.回文子串.html) 差不多是一样的但647.回文子串更基本一点建议可以先做647.回文子串
## 暴力解法

View File

@ -8,11 +8,11 @@
> 用哈希表解决了[两数之和](https://mp.weixin.qq.com/s/uVAtjOHSeqymV8FeQbliJQ),那么三数之和呢?
> 用哈希表解决了[两数之和](https://programmercarl.com/0001.两数之和.html),那么三数之和呢?
# 第15题. 三数之和
https://leetcode-cn.com/problems/3sum/
[力扣题目链接](https://leetcode-cn.com/problems/3sum/)
给你一个包含 n 个整数的数组 nums判断 nums 中是否存在三个元素 abc 使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
@ -163,13 +163,13 @@ public:
# 思考题
既然三数之和可以使用双指针法我们之前讲过的[1.两数之和](https://mp.weixin.qq.com/s/vaMsLnH-f7_9nEK4Cuu3KQ)可不可以使用双指针法呢
既然三数之和可以使用双指针法我们之前讲过的[1.两数之和](https://programmercarl.com/0001.两数之和.html)可不可以使用双指针法呢
如果不能题意如何更改就可以使用双指针法呢 **大家留言说出自己的想法吧!**
两数之和 就不能使用双指针法因为[1.两数之和](https://mp.weixin.qq.com/s/vaMsLnH-f7_9nEK4Cuu3KQ)要求返回的是索引下表 而双指针法一定要排序一旦排序之后原数组的索引就被改变了
两数之和 就不能使用双指针法因为[1.两数之和](https://programmercarl.com/0001.两数之和.html)要求返回的是索引下表 而双指针法一定要排序一旦排序之后原数组的索引就被改变了
如果[1.两数之和](https://mp.weixin.qq.com/s/vaMsLnH-f7_9nEK4Cuu3KQ)要求返回的是数值的话就可以使用双指针法了
如果[1.两数之和](https://programmercarl.com/0001.两数之和.html)要求返回的是数值的话就可以使用双指针法了

View File

@ -9,7 +9,7 @@
# 17.电话号码的字母组合
题目链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/
[力扣题目链接](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
@ -29,7 +29,7 @@
如果输入"233"呢那么就三层for循环如果"2333"呢就四层for循环.......
大家应该感觉出和[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)遇到的一样的问题就是这for循环的层数如何写出来此时又是回溯法登场的时候了。
大家应该感觉出和[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)遇到的一样的问题就是这for循环的层数如何写出来此时又是回溯法登场的时候了。
理解本题后,要解决如下三个问题:
@ -58,7 +58,7 @@ const string letterMap[10] = {
## 回溯法来解决n个for循环的问题
对于回溯法还不了解的同学看这篇:[关于回溯算法,你该了解这些!](https://mp.weixin.qq.com/s/gjSgJbNbd1eAA5WkA-HeWw)
对于回溯法还不了解的同学看这篇:[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)
例如:输入:"23",抽象为树形结构,如图所示:
@ -75,7 +75,7 @@ const string letterMap[10] = {
再来看参数参数指定是有题目中给的string digits然后还要有一个参数就是int型的index。
注意这个index可不是 [回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)和[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)中的startIndex了。
注意这个index可不是 [回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)和[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)中的startIndex了。
这个index是记录遍历第几个数字了就是用来遍历digits的题目中给出数字字符串同时index也表示树的深度。
@ -120,9 +120,9 @@ for (int i = 0; i < letters.size(); i++) {
}
```
**注意这里for循环可不像是在[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)和[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)中从startIndex开始遍历的**
**注意这里for循环可不像是在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)和[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)中从startIndex开始遍历的**
**因为本题每一个数字代表的是不同集合,也就是求不同集合之间的组合,而[77. 组合](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)和[216.组合总和III](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)都是是求同一个集合中的组合!**
**因为本题每一个数字代表的是不同集合,也就是求不同集合之间的组合,而[77. 组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)都是是求同一个集合中的组合!**
注意输入1 * #按键等等异常情况
@ -134,7 +134,7 @@ for (int i = 0; i < letters.size(); i++) {
## C++代码
关键地方都讲完了,按照[关于回溯算法,你该了解这些!](https://mp.weixin.qq.com/s/gjSgJbNbd1eAA5WkA-HeWw)中的回溯法模板不难写出如下C++代码:
关键地方都讲完了,按照[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中的回溯法模板不难写出如下C++代码:
```c++
@ -224,13 +224,13 @@ public:
};
```
我不建议把回溯藏在递归的参数里这种写法,很不直观,我在[二叉树:以为使用了递归,其实还隐藏着回溯](https://mp.weixin.qq.com/s/ivLkHzWdhjQQD1rQWe6zWA)这篇文章中也深度分析了,回溯隐藏在了哪里。
我不建议把回溯藏在递归的参数里这种写法,很不直观,我在[二叉树:以为使用了递归,其实还隐藏着回溯](https://programmercarl.com/二叉树中递归带着回溯.html)这篇文章中也深度分析了,回溯隐藏在了哪里。
所以大家可以按照版本一来写就可以了。
# 总结
本篇将题目的三个要点一一列出,并重点强调了和前面讲解过的[77. 组合](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)和[216.组合总和III](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)的区别,本题是多个集合求组合,所以在回溯的搜索过程中,都有一些细节需要注意的。
本篇将题目的三个要点一一列出,并重点强调了和前面讲解过的[77. 组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)的区别,本题是多个集合求组合,所以在回溯的搜索过程中,都有一些细节需要注意的。
其实本题不算难,但也处处是细节,大家还要自己亲自动手写一写。

View File

@ -12,7 +12,7 @@
# 第18题. 四数之和
https://leetcode-cn.com/problems/4sum/
[力扣题目链接](https://leetcode-cn.com/problems/4sum/)
题意给定一个包含 n 个整数的数组 nums 和一个目标值 target判断 nums 中是否存在四个元素 abc 和 d 使得 a + b + c + d 的值与 target 相等找出所有满足条件且不重复的四元组。
@ -31,37 +31,37 @@ https://leetcode-cn.com/problems/4sum/
# 思路
四数之和,和[15.三数之和](https://mp.weixin.qq.com/s/QfTNEByq1YlNSXRKEumwHg)是一个思路,都是使用双指针法, 基本解法就是在[15.三数之和](https://mp.weixin.qq.com/s/QfTNEByq1YlNSXRKEumwHg) 的基础上再套一层for循环。
四数之和,和[15.三数之和](https://programmercarl.com/0015.三数之和.html)是一个思路,都是使用双指针法, 基本解法就是在[15.三数之和](https://programmercarl.com/0015.三数之和.html) 的基础上再套一层for循环。
但是有一些细节需要注意,例如: 不要判断`nums[k] > target` 就返回了,三数之和 可以通过 `nums[i] > 0` 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。大家亲自写代码就能感受出来
[15.三数之和](https://mp.weixin.qq.com/s/QfTNEByq1YlNSXRKEumwHg)的双指针解法是一层for循环num[i]为确定值然后循环内有left和right下表作为双指针找到nums[i] + nums[left] + nums[right] == 0。
[15.三数之和](https://programmercarl.com/0015.三数之和.html)的双指针解法是一层for循环num[i]为确定值然后循环内有left和right下表作为双指针找到nums[i] + nums[left] + nums[right] == 0。
四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值依然是循环内有left和right下表作为双指针找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况三数之和的时间复杂度是O(n^2)四数之和的时间复杂度是O(n^3) 。
那么一样的道理,五数之和、六数之和等等都采用这种解法。
对于[15.三数之和](https://mp.weixin.qq.com/s/QfTNEByq1YlNSXRKEumwHg)双指针法就是将原本暴力O(n^3)的解法降为O(n^2)的解法四数之和的双指针解法就是将原本暴力O(n^4)的解法降为O(n^3)的解法。
对于[15.三数之和](https://programmercarl.com/0015.三数之和.html)双指针法就是将原本暴力O(n^3)的解法降为O(n^2)的解法四数之和的双指针解法就是将原本暴力O(n^4)的解法降为O(n^3)的解法。
之前我们讲过哈希表的经典题目:[454.四数相加II](https://mp.weixin.qq.com/s/12g_w6RzHuEpFts1pT6BWw)相对于本题简单很多因为本题是要求在一个集合中找出四个数相加等于target同时四元组不能重复。
之前我们讲过哈希表的经典题目:[454.四数相加II](https://programmercarl.com/0454.四数相加II.html)相对于本题简单很多因为本题是要求在一个集合中找出四个数相加等于target同时四元组不能重复。
而[454.四数相加II](https://mp.weixin.qq.com/s/12g_w6RzHuEpFts1pT6BWw)是四个独立的数组只要找到A[i] + B[j] + C[k] + D[l] = 0就可以不用考虑有重复的四个元素相加等于0的情况所以相对于本题还是简单了不少
而[454.四数相加II](https://programmercarl.com/0454.四数相加II.html)是四个独立的数组只要找到A[i] + B[j] + C[k] + D[l] = 0就可以不用考虑有重复的四个元素相加等于0的情况所以相对于本题还是简单了不少
我们来回顾一下,几道题目使用了双指针法。
双指针法将时间复杂度O(n^2)的解法优化为 O(n)的解法。也就是降一个数量级,题目如下:
* [27.移除元素](https://mp.weixin.qq.com/s/RMkulE4NIb6XsSX83ra-Ww)
* [15.三数之和](https://mp.weixin.qq.com/s/QfTNEByq1YlNSXRKEumwHg)
* [18.四数之和](https://mp.weixin.qq.com/s/nQrcco8AZJV1pAOVjeIU_g)
* [27.移除元素](https://programmercarl.com/0027.移除元素.html)
* [15.三数之和](https://programmercarl.com/0015.三数之和.html)
* [18.四数之和](https://programmercarl.com/0018.四数之和.html)
操作链表:
* [206.反转链表](https://mp.weixin.qq.com/s/ckEvIVGcNLfrz6OLOMoT0A)
* [19.删除链表的倒数第N个节点](https://mp.weixin.qq.com/s/gxu65X1343xW_sBrkTz0Eg)
* [面试题 02.07. 链表相交](https://mp.weixin.qq.com/s/BhfFfaGvt9Zs7UmH4YehZw)
* [142题.环形链表II](https://mp.weixin.qq.com/s/gt_VH3hQTqNxyWcl1ECSbQ)
* [206.反转链表](https://programmercarl.com/0206.翻转链表.html)
* [19.删除链表的倒数第N个节点](https://programmercarl.com/0019.删除链表的倒数第N个节点.html)
* [面试题 02.07. 链表相交](https://programmercarl.com/面试题02.07.链表相交.html)
* [142题.环形链表II](https://programmercarl.com/0142.环形链表II.html)
双指针法在字符串题目中还有很多应用,后面还会介绍到。

View File

@ -11,7 +11,7 @@
## 19.删除链表的倒数第N个节点
题目链接:https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
[力扣题目链接](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/)
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
@ -41,7 +41,7 @@
分为如下几步:
* 首先这里我推荐大家使用虚拟头结点,这样方面处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: [链表:听说用虚拟头节点会方便很多?](https://mp.weixin.qq.com/s/L5aanfALdLEwVWGvyXPDqA)
* 首先这里我推荐大家使用虚拟头结点,这样方面处理删除实际头结点的逻辑,如果虚拟头结点不清楚,可以看这篇: [链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)
* 定义fast指针和slow指针初始值为虚拟头结点如图

View File

@ -12,7 +12,7 @@
# 20. 有效的括号
https://leetcode-cn.com/problems/valid-parentheses/
[力扣题目链接](https://leetcode-cn.com/problems/valid-parentheses/)
给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

View File

@ -9,7 +9,7 @@
## 24. 两两交换链表中的节点
https://leetcode-cn.com/problems/swap-nodes-in-pairs/
[力扣题目链接](https://leetcode-cn.com/problems/swap-nodes-in-pairs/)
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
@ -24,7 +24,7 @@ https://leetcode-cn.com/problems/swap-nodes-in-pairs/
建议使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。
对虚拟头结点的操作,还不熟悉的话,可以看这篇[链表:听说用虚拟头节点会方便很多?](https://mp.weixin.qq.com/s/L5aanfALdLEwVWGvyXPDqA)。
对虚拟头结点的操作,还不熟悉的话,可以看这篇[链表:听说用虚拟头节点会方便很多?](https://programmercarl.com/0203.移除链表元素.html)。
接下来就是交换相邻两个元素了,**此时一定要画图,不画图,操作多个指针很容易乱,而且要操作的先后顺序**

View File

@ -9,7 +9,7 @@
## 27. 移除元素
题目地址:https://leetcode-cn.com/problems/remove-element/
[力扣题目链接](https://leetcode-cn.com/problems/remove-element/)
给你一个数组 nums 和一个值 val你需要 原地 移除所有数值等于 val 的元素并返回移除后数组的新长度。
@ -34,7 +34,7 @@
**要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。**
数组的基础知识可以看这里[程序员算法面试中,必须掌握的数组理论知识](https://mp.weixin.qq.com/s/c2KABb-Qgg66HrGf8z-8Og)。
数组的基础知识可以看这里[程序员算法面试中,必须掌握的数组理论知识](https://programmercarl.com/数组理论基础.html)。
### 暴力解法
@ -106,7 +106,7 @@ public:
* 时间复杂度:$O(n)$
* 空间复杂度:$O(1)$
旧文链接:[数组:就移除个元素很难么?](https://mp.weixin.qq.com/s/wj0T-Xs88_FHJFwayElQlA)
旧文链接:[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)
## 相关题目推荐

View File

@ -11,7 +11,7 @@
# 28. 实现 strStr()
https://leetcode-cn.com/problems/implement-strstr/
[力扣题目链接](https://leetcode-cn.com/problems/implement-strstr/)
实现 strStr() 函数。

View File

@ -11,7 +11,7 @@
# 31.下一个排列
链接:https://leetcode-cn.com/problems/next-permutation/
[力扣题目链接](https://leetcode-cn.com/problems/next-permutation/)
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

View File

@ -35,8 +35,8 @@
对二分还不了解的同学先做这两题:
* [704.二分查找](https://mp.weixin.qq.com/s/4X-8VRgnYRGd5LYGZ33m4w)
* [35.搜索插入位置](https://mp.weixin.qq.com/s/fCf5QbPDtE6SSlZ1yh_q8Q)
* [704.二分查找](https://programmercarl.com/0704.二分查找.html)
* [35.搜索插入位置](https://programmercarl.com/0035.搜索插入位置.html)
下面我来把所有情况都讨论一下。
@ -56,9 +56,9 @@
## 寻找右边界
先来寻找右边界,至于二分查找,如果看过[704.二分查找](https://mp.weixin.qq.com/s/4X-8VRgnYRGd5LYGZ33m4w)就会知道二分查找中什么时候用while (left <= right)有什么时候用while (left < right)其实只要清楚**循环不变量**很容易区分两种写法
先来寻找右边界,至于二分查找,如果看过[704.二分查找](https://programmercarl.com/0704.二分查找.html)就会知道二分查找中什么时候用while (left <= right)有什么时候用while (left < right)其实只要清楚**循环不变量**很容易区分两种写法
那么这里我采用while (left <= right)的写法区间定义为[left, right]即左闭又闭的区间如果这里有点看不懂了强烈建议把[704.二分查找](https://mp.weixin.qq.com/s/4X-8VRgnYRGd5LYGZ33m4w)这篇文章先看了704题目做了之后再做这道题目就好很多了
那么这里我采用while (left <= right)的写法区间定义为[left, right]即左闭又闭的区间如果这里有点看不懂了强烈建议把[704.二分查找](https://programmercarl.com/0704.二分查找.html)这篇文章先看了704题目做了之后再做这道题目就好很多了
确定好计算出来的右边界是不包好target的右边界左边界同理

View File

@ -11,7 +11,7 @@
# 35.搜索插入位置
题目地址:https://leetcode-cn.com/problems/search-insert-position/
[力扣题目链接](https://leetcode-cn.com/problems/search-insert-position/)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

View File

@ -11,7 +11,7 @@
## 37. 解数独
题目地址:https://leetcode-cn.com/problems/sudoku-solver/
[力扣题目链接](https://leetcode-cn.com/problems/sudoku-solver/)
编写一个程序,通过填充空格来解决数独问题。
@ -40,11 +40,11 @@
怎么做二维递归呢?
大家已经跟着「代码随想录」刷过了如下回溯法题目,例如:[77.组合(组合问题)](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)[131.分割回文串(分割问题)](https://mp.weixin.qq.com/s/Pb1epUTbU8fHIht-g_MS5Q)[78.子集(子集问题)](https://mp.weixin.qq.com/s/NNRzX-vJ_pjK4qxohd_LtA)[46.全排列(排列问题)](https://mp.weixin.qq.com/s/SCOjeMX1t41wcvJq49GhMw),以及[51.N皇后N皇后问题](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg),其实这些题目都是一维递归。
大家已经跟着「代码随想录」刷过了如下回溯法题目,例如:[77.组合(组合问题)](https://programmercarl.com/0077.组合.html)[131.分割回文串(分割问题)](https://programmercarl.com/0131.分割回文串.html)[78.子集(子集问题)](https://programmercarl.com/0078.子集.html)[46.全排列(排列问题)](https://programmercarl.com/0046.全排列.html),以及[51.N皇后N皇后问题](https://programmercarl.com/0051.N皇后.html),其实这些题目都是一维递归。
**如果以上这几道题目没有做过的话,不建议上来就做这道题哈!**
[N皇后问题](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg)是因为每一行每一列只放一个皇后只需要一层for循环遍历一行递归来来遍历列然后一行一列确定皇后的唯一位置。
[N皇后问题](https://programmercarl.com/0051.N皇后.html)是因为每一行每一列只放一个皇后只需要一层for循环遍历一行递归来来遍历列然后一行一列确定皇后的唯一位置。
本题就不一样了,**本题中棋盘的每一个位置都要放一个数字并检查数字是否合法解数独的树形结构要比N皇后更宽更深**。
@ -59,7 +59,7 @@
**递归函数的返回值需要是bool类型为什么呢**
因为解数独找到一个符合的条件就在树的叶子节点上立刻就返回相当于找从根节点到叶子节点一条唯一路径所以需要使用bool返回值这一点在[回溯算法N皇后问题](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg)中已经介绍过了,一样的道理。
因为解数独找到一个符合的条件就在树的叶子节点上立刻就返回相当于找从根节点到叶子节点一条唯一路径所以需要使用bool返回值这一点在[回溯算法N皇后问题](https://programmercarl.com/0051.N皇后.html)中已经介绍过了,一样的道理。
代码如下:

View File

@ -9,7 +9,7 @@
## 39. 组合总和
题目链接:https://leetcode-cn.com/problems/combination-sum/
[力扣题目链接](https://leetcode-cn.com/problems/combination-sum/)
给定一个无重复元素的数组 candidates 和一个目标数 target 找出 candidates 中所有可以使数字和为 target 的组合。
@ -44,14 +44,14 @@ candidates 中的数字可以无限制重复被选取。
题目中的**无限制重复被选取,吓得我赶紧想想 出现0 可咋办**然后看到下面提示1 <= candidates[i] <= 200我就放心了。
本题和[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)和区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。
本题和[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)和区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。
本题搜索的过程抽象成树形结构如下:
![39.组合总和](https://img-blog.csdnimg.cn/20201223170730367.png)
注意图中叶子节点的返回条件因为本题没有组合数量要求仅仅是总和的限制所以递归没有层数的限制只要选取的元素总和超过target就返回
而在[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)和[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w) 中都可以知道要递归K层因为要取k个元素的组合。
而在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)和[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html) 中都可以知道要递归K层因为要取k个元素的组合。
## 回溯三部曲
@ -65,9 +65,9 @@ candidates 中的数字可以无限制重复被选取。
**本题还需要startIndex来控制for循环的起始位置对于组合问题什么时候需要startIndex呢**
我举过例子如果是一个集合来求组合的话就需要startIndex例如[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)。
我举过例子如果是一个集合来求组合的话就需要startIndex例如[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)。
如果是多个集合取组合各个集合之间相互不影响那么就不用startIndex例如[回溯算法:电话号码的字母组合](https://mp.weixin.qq.com/s/e2ua2cmkE_vpYjM3j6HY0A)
如果是多个集合取组合各个集合之间相互不影响那么就不用startIndex例如[回溯算法:电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)
**注意以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路,后面我再讲解排列的时候就重点介绍**
@ -103,7 +103,7 @@ if (sum == target) {
单层for循环依然是从startIndex开始搜索candidates集合。
**注意本题和[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)、[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)的一个区别是:本题元素为可重复选取的**
**注意本题和[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)、[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)的一个区别是:本题元素为可重复选取的**
如何重复选取呢,看代码,注释部分:
@ -117,7 +117,7 @@ for (int i = startIndex; i < candidates.size(); i++) {
}
```
按照[关于回溯算法,你该了解这些!](https://mp.weixin.qq.com/s/gjSgJbNbd1eAA5WkA-HeWw)中给出的模板不难写出如下C++完整代码:
按照[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中给出的模板不难写出如下C++完整代码:
```CPP
// 版本一
@ -213,14 +213,14 @@ public:
## 总结
本题和我们之前讲过的[回溯算法:求组合问题!](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)、[回溯算法:求组合总和!](https://mp.weixin.qq.com/s/HX7WW6ixbFZJASkRnCTC3w)有两点不同:
本题和我们之前讲过的[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)、[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)有两点不同:
* 组合没有数量要求
* 元素可无限重复选取
针对这两个问题,我都做了详细的分析。
并且给出了对于组合问题什么时候用startIndex什么时候不用并用[回溯算法:电话号码的字母组合](https://mp.weixin.qq.com/s/e2ua2cmkE_vpYjM3j6HY0A)做了对比。
并且给出了对于组合问题什么时候用startIndex什么时候不用并用[回溯算法:电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)做了对比。
最后还给出了本题的剪枝优化,这个优化如果是初学者的话并不容易想到。

View File

@ -11,7 +11,7 @@
## 40.组合总和II
题目链接:https://leetcode-cn.com/problems/combination-sum-ii/
[力扣题目链接](https://leetcode-cn.com/problems/combination-sum-ii/)
给定一个数组 candidates 和一个目标数 target 找出 candidates 中所有可以使数字和为 target 的组合。
@ -44,12 +44,12 @@ candidates 中的每个数字在每个组合中只能使用一次。
**如果对回溯算法基础还不了解的话,我还特意录制了一期视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/)** 可以结合题解和视频一起看,希望对大家理解回溯算法有所帮助。
这道题目和[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)如下区别:
这道题目和[39.组合总和](https://programmercarl.com/0039.组合总和.html)如下区别:
1. 本题candidates 中的每个数字在每个组合中只能使用一次。
2. 本题数组candidates的元素是有重复的而[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)是无重复元素的数组candidates
2. 本题数组candidates的元素是有重复的而[39.组合总和](https://programmercarl.com/0039.组合总和.html)是无重复元素的数组candidates
最后本题和[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)要求一样,解集不能包含重复的组合。
最后本题和[39.组合总和](https://programmercarl.com/0039.组合总和.html)要求一样,解集不能包含重复的组合。
**本题的难点在于区别2中集合数组candidates有重复元素但还不能有重复的组合**
@ -84,7 +84,7 @@ candidates 中的每个数字在每个组合中只能使用一次。
* **递归函数参数**
与[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)套路相同此题还需要加一个bool型数组used用来记录同一树枝上的元素是否使用过。
与[39.组合总和](https://programmercarl.com/0039.组合总和.html)套路相同此题还需要加一个bool型数组used用来记录同一树枝上的元素是否使用过。
这个集合去重的重任就是used来完成的。
@ -98,7 +98,7 @@ void backtracking(vector<int>& candidates, int target, int sum, int startIndex,
* **递归终止条件**
与[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)相同,终止条件为 `sum > target``sum == target`
与[39.组合总和](https://programmercarl.com/0039.组合总和.html)相同,终止条件为 `sum > target``sum == target`
代码如下:
@ -116,7 +116,7 @@ if (sum == target) {
* **单层搜索的逻辑**
这里与[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)最大的不同就是要去重了。
这里与[39.组合总和](https://programmercarl.com/0039.组合总和.html)最大的不同就是要去重了。
前面我们提到:要去重的是“同一树层上的使用过”,如果判断同一树层上元素(相同的元素)是否使用过了呢。
@ -244,7 +244,7 @@ public:
## 总结
本题同样是求组合总和但就是因为其数组candidates有重复元素而要求不能有重复的组合所以相对于[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)难度提升了不少。
本题同样是求组合总和但就是因为其数组candidates有重复元素而要求不能有重复的组合所以相对于[39.组合总和](https://programmercarl.com/0039.组合总和.html)难度提升了不少。
**关键是去重的逻辑,代码很简单,网上一搜一大把,但几乎没有能把这块代码含义讲明白的,基本都是给出代码,然后说这就是去重了,究竟怎么个去重法也是模棱两可**

View File

@ -11,7 +11,7 @@
# 42. 接雨水
题目链接:https://leetcode-cn.com/problems/trapping-rain-water/
[力扣题目链接](https://leetcode-cn.com/problems/trapping-rain-water/)
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
@ -27,7 +27,7 @@
* 输入height = [4,2,0,3,2,5]
* 输出9
 
# 思路
@ -186,7 +186,7 @@ public:
这个解法可以说是最不好理解的了,所以下面我花了大量的篇幅来介绍这种方法。
单调栈就是保持栈内元素有序。和[栈与队列:单调队列](https://mp.weixin.qq.com/s/Xgcqx5eBa3xZabt_LurnNQ)一样,需要我们自己维持顺序,没有现成的容器可以用。
单调栈就是保持栈内元素有序。和[栈与队列:单调队列](https://programmercarl.com/0239.滑动窗口最大值.html)一样,需要我们自己维持顺序,没有现成的容器可以用。
### 准备工作

View File

@ -11,7 +11,7 @@
## 45.跳跃游戏II
题目地址:https://leetcode-cn.com/problems/jump-game-ii/
[力扣题目链接](https://leetcode-cn.com/problems/jump-game-ii/)
给定一个非负整数数组,你最初位于数组的第一个位置。
@ -30,7 +30,7 @@
## 思路
本题相对于[55.跳跃游戏](https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA)还是难了不少。
本题相对于[55.跳跃游戏](https://programmercarl.com/0055.跳跃游戏.html)还是难了不少。
但思路是相似的,还是要看最大覆盖范围。
@ -132,7 +132,7 @@ public:
## 总结
相信大家可以发现,这道题目相当于[55.跳跃游戏](https://mp.weixin.qq.com/s/606_N9j8ACKCODoCbV1lSA)难了不止一点。
相信大家可以发现,这道题目相当于[55.跳跃游戏](https://programmercarl.com/0055.跳跃游戏.html)难了不止一点。
但代码又十分简单,贪心就是这么巧妙。

View File

@ -9,7 +9,7 @@
## 46.全排列
题目链接:https://leetcode-cn.com/problems/permutations/
[力扣题目链接](https://leetcode-cn.com/problems/permutations/)
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
@ -30,11 +30,11 @@
**如果对回溯算法基础还不了解的话,我还特意录制了一期视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/)** 可以结合题解和视频一起看,希望对大家理解回溯算法有所帮助。
此时我们已经学习了[77.组合问题](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)、 [131.分割回文串](https://mp.weixin.qq.com/s/Pb1epUTbU8fHIht-g_MS5Q)和[78.子集问题](https://mp.weixin.qq.com/s/NNRzX-vJ_pjK4qxohd_LtA),接下来看一看排列问题。
此时我们已经学习了[77.组合问题](https://programmercarl.com/0077.组合.html)、 [131.分割回文串](https://programmercarl.com/0131.分割回文串.html)和[78.子集问题](https://programmercarl.com/0078.子集.html),接下来看一看排列问题。
相信这个排列问题就算是让你用for循环暴力把结果搜索出来这个暴力也不是很好写。
所以正如我们在[关于回溯算法,你该了解这些!](https://mp.weixin.qq.com/s/gjSgJbNbd1eAA5WkA-HeWw)所讲的为什么回溯法是暴力搜索,效率这么低,还要用它?
所以正如我们在[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)所讲的为什么回溯法是暴力搜索,效率这么低,还要用它?
**因为一些问题能暴力搜出来就已经很不错了!**
@ -84,7 +84,7 @@ if (path.size() == nums.size()) {
* 单层搜索的逻辑
这里和[77.组合问题](https://mp.weixin.qq.com/s/OnBjbLzuipWz_u4QfmgcqQ)、[131.切割问题](https://mp.weixin.qq.com/s/Pb1epUTbU8fHIht-g_MS5Q)和[78.子集问题](https://mp.weixin.qq.com/s/NNRzX-vJ_pjK4qxohd_LtA)最大的不同就是for循环里不用startIndex了。
这里和[77.组合问题](https://programmercarl.com/0077.组合.html)、[131.切割问题](https://programmercarl.com/0131.分割回文串.html)和[78.子集问题](https://programmercarl.com/0078.子集.html)最大的不同就是for循环里不用startIndex了。
因为排列问题每次都要从头开始搜索例如元素1在[1,2]中已经使用过了,但是在[2,1]中还要再使用一次1。

View File

@ -10,7 +10,7 @@
## 47.全排列 II
题目链接:https://leetcode-cn.com/problems/permutations-ii/
[力扣题目链接](https://leetcode-cn.com/problems/permutations-ii/)
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
@ -33,11 +33,11 @@
**如果对回溯算法基础还不了解的话,我还特意录制了一期视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/)** 可以结合题解和视频一起看,希望对大家理解回溯算法有所帮助。
这道题目和[回溯算法:排列问题!](https://mp.weixin.qq.com/s/SCOjeMX1t41wcvJq49GhMw)的区别在与**给定一个可包含重复数字的序列**,要返回**所有不重复的全排列**。
这道题目和[回溯算法:排列问题!](https://programmercarl.com/0046.全排列.html)的区别在与**给定一个可包含重复数字的序列**,要返回**所有不重复的全排列**。
这里又涉及到去重了。
在[回溯算法:求组合总和(三)](https://mp.weixin.qq.com/s/_1zPYk70NvHsdY8UWVGXmQ) 、[回溯算法:求子集问题(二)](https://mp.weixin.qq.com/s/WJ4JNDRJgsW3eUN72Hh3uQ)我们分别详细讲解了组合问题和子集问题如何去重。
在[回溯算法:求组合总和(三)](https://programmercarl.com/0040.组合总和II.html) 、[回溯算法:求子集问题(二)](https://programmercarl.com/0090.子集II.html)我们分别详细讲解了组合问题和子集问题如何去重。
那么排列问题其实也是一样的套路。
@ -51,7 +51,7 @@
**一般来说:组合问题和排列问题是在树形结构的叶子节点上收集结果,而子集问题就是取树上所有节点的结果**
在[回溯算法:排列问题!](https://mp.weixin.qq.com/s/SCOjeMX1t41wcvJq49GhMw)中已经详解讲解了排列问题的写法,在[回溯算法:求组合总和(三)](https://mp.weixin.qq.com/s/_1zPYk70NvHsdY8UWVGXmQ) 、[回溯算法:求子集问题(二)](https://mp.weixin.qq.com/s/WJ4JNDRJgsW3eUN72Hh3uQ)中详细讲解的去重的写法,所以这次我就不用回溯三部曲分析了,直接给出代码,如下:
在[回溯算法:排列问题!](https://programmercarl.com/0046.全排列.html)中已经详解讲解了排列问题的写法,在[回溯算法:求组合总和(三)](https://programmercarl.com/0040.组合总和II.html) 、[回溯算法:求子集问题(二)](https://programmercarl.com/0090.子集II.html)中详细讲解的去重的写法,所以这次我就不用回溯三部曲分析了,直接给出代码,如下:
## C++代码