|
1 |
| -## 题目地址 |
| 1 | +# 题目地址 |
2 | 2 | https://leetcode-cn.com/problems/3sum/
|
3 | 3 |
|
4 |
| -## 思路 |
| 4 | +> 用哈希表解决了[两数之和](https://mp.weixin.qq.com/s/uVAtjOHSeqymV8FeQbliJQ),那么三数之和呢? |
5 | 5 |
|
6 |
| -### 哈希解法 |
| 6 | +# 第15题. 三数之和 |
7 | 7 |
|
| 8 | +给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。 |
8 | 9 |
|
9 |
| -两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。 |
10 |
| - |
11 |
| -把符合条件的三元组放进vector中,然后在去去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。 |
12 |
| - |
13 |
| -去重的过程不好处理,有很多小细节,如果在面试中很难想到位。 |
| 10 | +**注意:** 答案中不可以包含重复的三元组。 |
14 | 11 |
|
15 |
| -时间复杂度:O(n^2),但是运行时间很长,不好做剪枝操作 |
| 12 | +示例: |
16 | 13 |
|
17 |
| -### 双指针 |
| 14 | +给定数组 nums = [-1, 0, 1, 2, -1, -4], |
18 | 15 |
|
19 |
| -**其实这道题目使用哈希法并不十分合适**,因为在去重的操作中有很多细节需要注意,在面试中很难直接写出没有bug的代码,而且是用哈希法 在使用两层for循环的时候,能做的剪枝操作很有限,虽然时间复杂度是O(n^2),也是可以在leetcode上通过,但是程序的执行时间依然比较长 。 |
20 |
| - |
21 |
| -接下来我来介绍另一个解法:双指针法,**这道题目使用双指针法 要比哈希法高效一些**,那么来讲解一下具体实现的思路。 |
22 |
| - |
23 |
| -动画效果如下: |
| 16 | +满足要求的三元组集合为: |
| 17 | +[ |
| 18 | + [-1, 0, 1], |
| 19 | + [-1, -1, 2] |
| 20 | +] |
24 | 21 |
|
25 |
| -<video src='../video/15.三数之和.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div> |
26 | 22 |
|
27 |
| -拿这个nums数组来举例,首先将数组排序,然后 有一层for循环,i从下表0的地方开始,同时定一个下表left 定义在i+1的位置上,定义下表right 在数组结尾的位置上。 |
| 23 | +# 思路 |
28 | 24 |
|
29 |
| -我们依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i] b = nums[left] c = nums[right]。 |
| 25 | +## 哈希解法 |
30 | 26 |
|
31 |
| -接下来我们如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下表就应该想左移动,这样才能让三数之和小一些。 |
| 27 | +两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。 |
32 | 28 |
|
33 |
| -如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了, left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。 |
| 29 | +把符合条件的三元组放进vector中,然后在去去重,这样是非常费时的,很容易超时,也是这道题目通过率如此之低的根源所在。 |
34 | 30 |
|
| 31 | +去重的过程不好处理,有很多小细节,如果在面试中很难想到位。 |
35 | 32 |
|
36 |
| -时间复杂度:O(n^2) |
| 33 | +时间复杂度可以做到O(n^2),但还是比较费时的,因为不好做剪枝操作。 |
37 | 34 |
|
38 |
| -## C++代码 |
39 |
| - |
40 |
| -### 哈希法代码 |
| 35 | +大家可以尝试使用哈希法写一写,就知道其困难的程度了。 |
41 | 36 |
|
| 37 | +## 哈希法C++代码 |
42 | 38 | ```
|
43 | 39 | class Solution {
|
44 | 40 | public:
|
@@ -75,7 +71,32 @@ public:
|
75 | 71 | }
|
76 | 72 | };
|
77 | 73 | ```
|
78 |
| -### 双指针法代码 |
| 74 | + |
| 75 | +## 双指针 |
| 76 | + |
| 77 | +**其实这道题目使用哈希法并不十分合适**,因为在去重的操作中有很多细节需要注意,在面试中很难直接写出没有bug的代码。 |
| 78 | + |
| 79 | +而且使用哈希法 在使用两层for循环的时候,能做的剪枝操作很有限,虽然时间复杂度是O(n^2),也是可以在leetcode上通过,但是程序的执行时间依然比较长 。 |
| 80 | + |
| 81 | +接下来我来介绍另一个解法:双指针法,**这道题目使用双指针法 要比哈希法高效一些**,那么来讲解一下具体实现的思路。 |
| 82 | + |
| 83 | +动画效果如下: |
| 84 | + |
| 85 | +<video src='../video/15.三数之和.mp4' controls='controls' width='640' height='320' autoplay='autoplay'> Your browser does not support the video tag.</video></div> |
| 86 | + |
| 87 | +拿这个nums数组来举例,首先将数组排序,然后有一层for循环,i从下表0的地方开始,同时定一个下表left 定义在i+1的位置上,定义下表right 在数组结尾的位置上。 |
| 88 | + |
| 89 | +依然还是在数组中找到 abc 使得a + b +c =0,我们这里相当于 a = nums[i] b = nums[left] c = nums[right]。 |
| 90 | + |
| 91 | +接下来如何移动left 和right呢, 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了,因为数组是排序后了,所以right下表就应该向左移动,这样才能让三数之和小一些。 |
| 92 | + |
| 93 | +如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。 |
| 94 | + |
| 95 | +时间复杂度:O(n^2)。 |
| 96 | + |
| 97 | + |
| 98 | +## 双指针法C++代码 |
| 99 | + |
79 | 100 | ```
|
80 | 101 | class Solution {
|
81 | 102 | public:
|
@@ -129,5 +150,15 @@ public:
|
129 | 150 | };
|
130 | 151 | ```
|
131 | 152 |
|
| 153 | +# 思考题 |
| 154 | + |
| 155 | +既然三数之和可以使用双指针法,我们之前讲过的[两数之和](https://mp.weixin.qq.com/s/uVAtjOHSeqymV8FeQbliJQ),可不可以使用双指针法呢? |
| 156 | + |
| 157 | +如果不能,题意如何更改就可以使用双指针法呢? **大家留言说出自己的想法吧!** |
| 158 | + |
| 159 | +两数之和 就不能使用双指针法,因为[两数之和](https://mp.weixin.qq.com/s/uVAtjOHSeqymV8FeQbliJQ)要求返回的是索引下表, 而双指针法一定要排序,一旦排序之后原数组的索引就被改变了。 |
| 160 | + |
| 161 | +如果[两数之和](https://mp.weixin.qq.com/s/uVAtjOHSeqymV8FeQbliJQ)要求返回的是数值的话,就可以使用双指针法了。 |
| 162 | + |
132 | 163 | > 更过算法干货文章持续更新,可以微信搜索「代码随想录」第一时间围观,关注后,回复「Java」「C++」 「python」「简历模板」「数据结构与算法」等等,就可以获得我多年整理的学习资料。
|
133 | 164 |
|
0 commit comments