diff --git a/README.md b/README.md index 282a2369..82c28969 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,8 @@ ## 知识星球精选 +* [秋招下半场依然没offer,怎么办?](./problems/知识星球精选/秋招下半场依然没offer.md) +* [合适自己的就是最好的](./problems/知识星球精选/合适自己的就是最好的.md) * [为什么都说客户端会消失](./problems/知识星球精选/客三消.md) * [博士转计算机如何找工作](./problems/知识星球精选/博士转行计算机.md) * [不一样的七夕](./problems/知识星球精选/不一样的七夕.md) @@ -462,6 +464,8 @@ * [24.两两交换链表中的节点](./problems/0024.两两交换链表中的节点.md) * [234.回文链表](./problems/0234.回文链表.md) * [143.重排链表](./problems/0143.重排链表.md)【数组】【双向队列】【直接操作链表】 + + * [141.环形链表](./problems/0141.环形链表.md) ## 哈希表 diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index 6b5311ae..d3d7f61e 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -354,44 +354,6 @@ def is_valid(strs) end ``` -php: - -```php -function threeSum(array $nums): array -{ - $result = []; - $length = count($nums); - if ($length < 3) { - return []; - } - sort($nums); - for ($i = 0; $i < $length; $i++) { - // 如果大于0结束 - if ($nums[$i] > 0) break; - // 去重 - if ($i > 0 && $nums[$i] == $nums[$i - 1]) continue; - $left = $i + 1; - $right = $length - 1; - // 比较 - while ($left < $right) { - $sum = $nums[$i] + $nums[$left] + $nums[$right]; - if ($sum < 0) { - $left++; - } elseif ($sum > 0) { - $right--; - } else { - array_push($result, [$nums[$i], $nums[$left], $nums[$right]]); - while ($left < $right && $nums[$left] == $nums[$left + 1]) $left++; - while ($left < $right && $nums[$right - 1] == $nums[$right]) $right--; - $left++; - $right--; - } - } - } - - return $result; -} -``` PHP: ```php diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index 9891f0fe..e283b291 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -90,7 +90,8 @@ public: int left = i + 1; int right = nums.size() - 1; while (right > left) { - if (nums[k] + nums[i] + nums[left] + nums[right] > target) { + // nums[k] + nums[i] + nums[left] + nums[right] > target 会溢出 + if (nums[k] + nums[i] > target - (nums[left] + nums[right])) { right--; } else if (nums[k] + nums[i] + nums[left] + nums[right] < target) { left++; @@ -110,8 +111,8 @@ public: } return result; } - }; + ``` diff --git a/problems/0039.组合总和.md b/problems/0039.组合总和.md index 97987e6d..4836de9c 100644 --- a/problems/0039.组合总和.md +++ b/problems/0039.组合总和.md @@ -7,7 +7,7 @@
欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!
-## 39. 组合总和 +# 39. 组合总和 [力扣题目链接](https://leetcode-cn.com/problems/combination-sum/) @@ -37,21 +37,21 @@ candidates 中的数字可以无限制重复被选取。 [3,5] ] -## 思路 +# 思路 [B站视频讲解-组合总和](https://www.bilibili.com/video/BV1KT4y1M7HJ) 题目中的**无限制重复被选取,吓得我赶紧想想 出现0 可咋办**,然后看到下面提示:1 <= candidates[i] <= 200,我就放心了。 -本题和[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html),[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)和区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。 +本题和[77.组合](https://programmercarl.com/0077.组合.html),[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)和区别是:本题没有数量要求,可以无限重复,但是有总和的限制,所以间接的也是有个数的限制。 本题搜索的过程抽象成树形结构如下:  注意图中叶子节点的返回条件,因为本题没有组合数量要求,仅仅是总和的限制,所以递归没有层数的限制,只要选取的元素总和超过target,就返回! -而在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)和[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html) 中都可以知道要递归K层,因为要取k个元素的组合。 +而在[77.组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html) 中都可以知道要递归K层,因为要取k个元素的组合。 ## 回溯三部曲 @@ -65,9 +65,9 @@ candidates 中的数字可以无限制重复被选取。 **本题还需要startIndex来控制for循环的起始位置,对于组合问题,什么时候需要startIndex呢?** -我举过例子,如果是一个集合来求组合的话,就需要startIndex,例如:[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html),[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)。 +我举过例子,如果是一个集合来求组合的话,就需要startIndex,例如:[77.组合](https://programmercarl.com/0077.组合.html),[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)。 -如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:[回溯算法:电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html) +如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:[17.电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html) **注意以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路,后面我再讲解排列的时候就重点介绍**。 @@ -103,7 +103,7 @@ if (sum == target) { 单层for循环依然是从startIndex开始,搜索candidates集合。 -**注意本题和[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)、[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)的一个区别是:本题元素为可重复选取的**。 +**注意本题和[77.组合](https://programmercarl.com/0077.组合.html)、[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)的一个区别是:本题元素为可重复选取的**。 如何重复选取呢,看代码,注释部分: @@ -211,16 +211,16 @@ public: }; ``` -## 总结 +# 总结 -本题和我们之前讲过的[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)、[回溯算法:求组合总和!](https://programmercarl.com/0216.组合总和III.html)有两点不同: +本题和我们之前讲过的[77.组合](https://programmercarl.com/0077.组合.html)、[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)有两点不同: * 组合没有数量要求 * 元素可无限重复选取 针对这两个问题,我都做了详细的分析。 -并且给出了对于组合问题,什么时候用startIndex,什么时候不用,并用[回溯算法:电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)做了对比。 +并且给出了对于组合问题,什么时候用startIndex,什么时候不用,并用[17.电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)做了对比。 最后还给出了本题的剪枝优化,这个优化如果是初学者的话并不容易想到。 @@ -232,10 +232,10 @@ public: -## 其他语言版本 +# 其他语言版本 -Java: +## Java ```Java // 剪枝优化 class Solution { @@ -264,7 +264,7 @@ class Solution { } ``` -Python: +## Python ```python3 class Solution: def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: @@ -284,10 +284,9 @@ class Solution: backtrack(candidates,target,0,0) return res ``` -Go: - -> 主要在于递归中传递下一个数字 +## Go +主要在于递归中传递下一个数字 ```go func combinationSum(candidates []int, target int) [][]int { @@ -319,7 +318,8 @@ func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int) } ``` -JavaScript: + +## JavaScript: ```js var combinationSum = function(candidates, target) { @@ -346,7 +346,7 @@ var combinationSum = function(candidates, target) { }; ``` -C: +## C ```c int* path; int pathTop; diff --git a/problems/0040.组合总和II.md b/problems/0040.组合总和II.md index 8925ef81..d6f4dac9 100644 --- a/problems/0040.组合总和II.md +++ b/problems/0040.组合总和II.md @@ -9,7 +9,7 @@ > 这篇可以说是全网把组合问题如何去重,讲的最清晰的了! -## 40.组合总和II +# 40.组合总和II [力扣题目链接](https://leetcode-cn.com/problems/combination-sum-ii/) @@ -39,7 +39,7 @@ candidates 中的每个数字在每个组合中只能使用一次。 [5] ] -## 思路 +# 思路 **如果对回溯算法基础还不了解的话,我还特意录制了一期视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/)** 可以结合题解和视频一起看,希望对大家理解回溯算法有所帮助。 @@ -157,7 +157,6 @@ for (int i = startIndex; i < candidates.size() && sum + candidates[i] <= target; **注意sum + candidates[i] <= target为剪枝操作,在[39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)有讲解过!** -## C++代码 回溯三部曲分析完了,整体C++代码如下: @@ -242,7 +241,7 @@ public: ``` -## 总结 +# 总结 本题同样是求组合总和,但就是因为其数组candidates有重复元素,而要求不能有重复的组合,所以相对于[39.组合总和](https://programmercarl.com/0039.组合总和.html)难度提升了不少。 @@ -254,10 +253,10 @@ public: -## 其他语言版本 +# 其他语言版本 -Java: +## Java ```Java class Solution { List