diff --git a/README.md b/README.md index 6b75cf41..62af988d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,7 @@ LeetCode 最强题解(持续更新中): |题目 | 类型 | 解题方法 | |---|---| ---| |[0000.两数之和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0000.两数之和.md) | 数组|**暴力** **哈希**| +|[0015.三数之和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0015.三数之和.md) | 数组|**双指针** 哈希| |[0021.合并两个有序链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0021.合并两个有序链表.md) |链表 |**模拟** | |[0026.删除排序数组中的重复项](https://github.com/youngyangyang04/leetcode/blob/master/problems/0026.删除排序数组中的重复项.md) |数组 |**暴力** **快慢指针** | |[0027.移除元素](https://github.com/youngyangyang04/leetcode/blob/master/problems/0027.移除元素.md) |数组 | **暴力** **快慢指针**| @@ -20,10 +21,12 @@ LeetCode 最强题解(持续更新中): |[0203.移除链表元素](https://github.com/youngyangyang04/leetcode/blob/master/problems/0203.移除链表元素.md) |链表 |**模拟** **虚拟头结点**| |[0206.翻转链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0206.翻转链表.md) |链表 | **模拟** **递归**| |[0209.长度最小的子数组](https://github.com/youngyangyang04/leetcode/blob/master/problems/0209.长度最小的子数组.md) |数组 | **暴力** **滑动窗口**| +|[0219.存在重复元素II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0219.存在重复元素II.md) | 哈希表 | **哈希** | |[0237.删除链表中的节点](https://github.com/youngyangyang04/leetcode/blob/master/problems/0237.删除链表中的节点.md) |链表 | **原链表移除** **添加虚拟节点** 递归| |[0349.两个数组的交集](https://github.com/youngyangyang04/leetcode/blob/master/problems/0349.两个数组的交集.md) |哈希表 |**哈希**| |[0350.两个数组的交集II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0350.两个数组的交集II.md) |哈希表 |**哈希**| |[0383.赎金信](https://github.com/youngyangyang04/leetcode/blob/master/problems/0383.赎金信.md) |数组 |**暴力** **字典计数**| +|[0454.四数相加II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0454.四数相加II.md) |哈希表 | **哈希**| |[0575.分糖果.md](https://github.com/youngyangyang04/leetcode/blob/master/problems/0575.分糖果.md) |哈希表 |**哈希**| |[0705.设计哈希集合.md](https://github.com/youngyangyang04/leetcode/blob/master/problems/0705.设计哈希集合.md) |哈希表 |**模拟**| |[0707.设计链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0707.设计链表.md) |链表 |**模拟**| diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index 8bc3ac0c..ecd40033 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -1,15 +1,71 @@ ## 题目地址 +https://leetcode-cn.com/problems/3sum/ ## 思路 -## 哈希解法 +### 哈希解法 -去重的过程不好处理,有很多小细节,在面试中很难想到为 +去重的过程不好处理,有很多小细节,如果在面试中很难想到位,需要在oj上不断尝试 -## 双指针 +时间复杂度:O(n^2) -推荐使用这个方法,排序后用双指针前后操作,比较容易达到去重的目的 +### 双指针 -O(n^2) +推荐使用这个方法,排序后用双指针前后操作,比较容易达到去重的目的,但也有一些细节需要注意,我在如下代码详细注释了需要注意的点 + +时间复杂度:O(n^2) + +## 代码 + +``` +class Solution { +public: + vector> threeSum(vector& nums) { + vector> result; + sort(nums.begin(), nums.end()); + for (int i = 0; i < nums.size(); i++) { + // 排序之后如果第一个元素已经大于零,那么无论如何组合都不可能凑成三元组,直接返回结果就可以了 + if (nums[i] > 0) { + return result; + } + // 错误去重方法,将会漏掉-1,-1,2 这种情况 + /* + if (nums[i] == nums[i + 1]) { + continue; + } + */ + // 正确去重方法 + if (i > 0 && nums[i] == nums[i - 1]) { + continue; + } + int left = i + 1; + int right = nums.size() - 1; + while (right > left) { + // 去重复逻辑如果放在这里,0,0,0 的情况,可能直接导致 right<=left 了,从而漏掉了 0,0,0 这种三元组 + /* + while (right > left && nums[right] == nums[right - 1]) right--; + while (right > left && nums[left] == nums[left + 1]) left++; + */ + if (nums[i] + nums[left] + nums[right] > 0) { + right--; + } else if (nums[i] + nums[left] + nums[right] < 0) { + left++; + } else { + result.push_back(vector{nums[i], nums[left], nums[right]}); + // 去重逻辑应该放在找到一个三元组之后 + while (right > left && nums[right] == nums[right - 1]) right--; + while (right > left && nums[left] == nums[left + 1]) left++; + + // 找到答案时,双指针同时收缩 + right--; + left++; + } + } + + } + return result; + } +}; +``` > 更多精彩文章持续更新,可以微信搜索「 代码随想录」第一时间阅读,关注后有大量的学习资料和简历模板可以免费领取,本文 [GitHub](https://github.com/youngyangyang04/leetcode-master ):https://github.com/youngyangyang04/leetcode-master 已经收录,欢迎star,fork,共同学习,一起进步。 diff --git a/problems/0021.合并两个有序链表.md b/problems/0021.合并两个有序链表.md index f9f8185f..2322a003 100644 --- a/problems/0021.合并两个有序链表.md +++ b/problems/0021.合并两个有序链表.md @@ -1,4 +1,13 @@ +## 题目地址 +https://leetcode-cn.com/problems/merge-two-sorted-lists/ + +## 思路 + +链表的基本操作,一下代码中有详细注释 + + +## 代码 ``` /** diff --git a/problems/0219.存在重复元素II.md b/problems/0219.存在重复元素II.md new file mode 100644 index 00000000..926d79b4 --- /dev/null +++ b/problems/0219.存在重复元素II.md @@ -0,0 +1,33 @@ + +## 题目地址 +https://leetcode-cn.com/problems/contains-duplicate-ii/ + +## 思路 + +使用哈希策略,map数据结构来记录数组元素和对应的元素所在下表 + +## C++代码 + +``` +class Solution { +public: + bool containsNearbyDuplicate(vector& nums, int k) { + unordered_map map; // key: 数组元素, value:元素所在下表 + for (int i = 0; i < nums.size(); i++) { + if (map.find(nums[i]) != map.end()) { // 找到了在索引i之前就出现过nums[i]这个元素 + int distance = i - map[nums[i]]; + if (distance <= k) { + return true; + } + map[nums[i]] = i; // 更新元素nums[i]所在的最新位置i + } else { // 如果map里面没有,就把插入一条数据<元素,元素所在的下表> + map[nums[i]] = i; + } + } + return false; + } +}; +``` + +> 笔者在先后在腾讯和百度从事技术研发多年,利用工作之余重刷leetcode,本文 [GitHub](https://github.com/youngyangyang04/leetcode-master ):https://github.com/youngyangyang04/leetcode-master 已经收录,欢迎star,fork,共同学习,一起进步。 + diff --git a/problems/0220.存在重复元素III.md b/problems/0220.存在重复元素III.md new file mode 100644 index 00000000..c6404765 --- /dev/null +++ b/problems/0220.存在重复元素III.md @@ -0,0 +1,22 @@ + + + +``` +class Solution { +public: + bool containsNearbyAlmostDuplicate(vector& nums, int k, int t) { + multiset s; + if(nums.empty() || k==0) return false; + for(int i=0;ik){ + s.erase(nums[i-k-1]); + } + auto index = s.lower_bound(nums[i]-t); + if(index!=s.end() && abs(*index-nums[i])<=t) return true; + s.insert(nums[i]); + + } + return false; + } +}; +``` diff --git a/problems/0454.四数相加II.md b/problems/0454.四数相加II.md new file mode 100644 index 00000000..4d8942df --- /dev/null +++ b/problems/0454.四数相加II.md @@ -0,0 +1,43 @@ +## 题目地址 +https://leetcode-cn.com/problems/4sum-ii/ + +## 思路 + +本题使用哈希表映射的方法 + +那么为什么0015.三数之和不适用哈希表映射的方法呢,感觉上 这道题目都是四个数之和都可以用哈希,三数之和怎么就用不了哈希呢 + +因为题目0015.三数之和,使用哈希的方法在不超时的情况下做到对结果去重很困难 + +而这道题目 相当于说 不用考虑重复元素,是四个独立的数组,所以相对于题目0015.三数之和,还是简单了不少 + +## C++代码 + +``` +class Solution { +public: + int fourSumCount(vector& A, vector& B, vector& C, vector& D) { + unordered_map umap; + for (int x : A) { + for (int y : B) { + if (umap.find(x + y) != umap.end()) { + umap[x + y]++; + } else { + umap[x + y] = 1; + } + } + } + int count = 0; + for (int x : C) { + for (int y : D) { + if (umap.find(0 - (x + y)) != umap.end()) { + count += umap[0 - (x + y)]; // 注意这里是加上umap[0 - (x + y)]的值 + } + } + } + return count; + } +}; +``` + +> 更多精彩文章持续更新,可以微信搜索「 代码随想录」第一时间阅读,关注后有大量的学习资料和简历模板可以免费领取,本文 [GitHub](https://github.com/youngyangyang04/leetcode-master ):https://github.com/youngyangyang04/leetcode-master 已经收录,欢迎star,fork,共同学习,一起进步。