[LeetCode] 3Sum 三数之和
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4},
A solution set is:
(-1, 0, 1)
(-1, -1, 2)
这道题让我们求三数之和,比之前那道 Two Sum 要复杂一些,博主考虑过先 fix 一个数,然后另外两个数使用 Two Sum 那种 HashMap 的解法,但是会有重复结果出现,就算使用 TreeSet 来去除重复也不行,会 TLE,看来此题并不是考 Two Sum 的解法。来分析一下这道题的特点,要找出三个数且和为0,那么除了三个数全是0的情况之外,肯定会有负数和正数,还是要先 fix 一个数,然后去找另外两个数,只要找到两个数且和为第一个 fix 数的相反数就行了,既然另外两个数不能使用 Two Sum 的那种解法来找,如何能更有效的定位呢?我们肯定不希望遍历所有两个数的组合吧,所以如果数组是有序的,那么就可以用双指针以线性时间复杂度来遍历所有满足题意的两个数组合。
对原数组进行排序,然后开始遍历排序后的数组,这里注意不是遍历到最后一个停止,而是到倒数第三个就可以了。这里可以先做个剪枝优化,就是当遍历到正数的时候就 break,为啥呢,因为数组现在是有序的了,如果第一个要 fix 的数就是正数了,则后面的数字就都是正数,就永远不会出现和为0的情况了。然后还要加上重复就跳过的处理,处理方法是从第二个数开始,如果和前面的数字相等,就跳过,因为不想把相同的数字fix两次。对于遍历到的数,用0减去这个 fix 的数得到一个 target,然后只需要再之后找到两个数之和等于 target 即可。用两个指针分别指向 fix 数字之后开始的数组首尾两个数,如果两个数和正好为 target,则将这两个数和 fix 的数一起存入结果中。然后就是跳过重复数字的步骤了,两个指针都需要检测重复数字。如果两数之和小于 target,则将左边那个指针i右移一位,使得指向的数字增大一些。同理,如果两数之和大于 target,则将右边那个指针j左移一位,使得指向的数字减小一些,代码如下:
解法一:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
if (nums.empty() || nums.back() < || nums.front() > ) return {};
for (int k = ; k < (int)nums.size() - ; ++k) {
if (nums[k] > ) break;
if (k > && nums[k] == nums[k - ]) continue;
int target = - nums[k], i = k + , j = (int)nums.size() - ;
while (i < j) {
if (nums[i] + nums[j] == target) {
res.push_back({nums[k], nums[i], nums[j]});
while (i < j && nums[i] == nums[i + ]) ++i;
while (i < j && nums[j] == nums[j - ]) --j;
++i; --j;
} else if (nums[i] + nums[j] < target) ++i;
else --j;
}
}
return res;
}
};
或者我们也可以利用 TreeSet 的不能包含重复项的特点来防止重复项的产生,那么就不需要检测数字是否被 fix 过两次,不过个人觉得还是前面那种解法更好一些,参见代码如下:
解法二:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
set<vector<int>> res;
sort(nums.begin(), nums.end());
if (nums.empty() || nums.back() < || nums.front() > ) return {};
for (int k = ; k < (int)nums.size() - ; ++k) {
if (nums[k] > ) break;
int target = - nums[k], i = k + , j = (int)nums.size() - ;
while (i < j) {
if (nums[i] + nums[j] == target) {
res.insert({nums[k], nums[i], nums[j]});
while (i < j && nums[i] == nums[i + ]) ++i;
while (i < j && nums[j] == nums[j - ]) --j;
++i; --j;
} else if (nums[i] + nums[j] < target) ++i;
else --j;
}
}
return vector<vector<int>>(res.begin(), res.end());
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/15
类似题目:
参考资料:
https://leetcode.com/problems/3sum/
https://leetcode.com/problems/3sum/discuss/7380/Concise-O(N2)-Java-solution
https://leetcode.com/problems/3sum/discuss/7373/Share-my-simple-java-solution
http://www.lifeincode.net/programming/leetcode-two-sum-3-sum-3-sum-closest-and-4-sum-java/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 3Sum 三数之和的更多相关文章
- 【LeetCode】15. 3Sum 三数之和
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:3sum, 三数之和,题解,leetcode, 力扣,P ...
- LeetCode:三数之和【15】
LeetCode:三数之和[15] 题目描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的 ...
- [LeetCode] 15. 3Sum 三数之和
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...
- LeetCode 15. 三数之和(3Sum)
15. 三数之和 15. 3Sum 题目描述 Given an array nums of n integers, are there elements a, b, c in nums such th ...
- 【LeetCode】三数之和【排序,固定一个数,然后双指针寻找另外两个数】
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...
- Java实现 LeetCode 15 三数之和
15. 三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以 ...
- [Leetcode] 3sum 三数和
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...
- LeetCode——15. 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...
- LeetCode 15. 三数之和(3Sum)
题目描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...
随机推荐
- ASP.NET Core 中文文档 第三章 原理(5)错误处理
原文:Error Handling 作者:Steve Smith 翻译:谢炀(Kiler) 校对:高嵩(jack2gs).何镇汐 当你的ASP.NET应用发生错误的时候, 你可以采用本文所述的各种方法 ...
- logstash日志分析的配置和使用
logstash是一个数据分析软件,主要目的是分析log日志.整一套软件可以当作一个MVC模型,logstash是controller层,Elasticsearch是一个model层,kibana是v ...
- spring源码:BeanPostProcessor(li)
在spring管理Bean的初始化过程中,除了正常管理bean的实例化(初始化.参数注入等)外,还对外提供了丰富的对Bean操作的扩展.例如自定义初始化操作,自定义容器退出时Bean的销毁操作等等.这 ...
- 两种常用的C语言排序算法
1. 要求输入10个整数,从大到小排序输出 输入:2 0 3 -4 8 9 5 1 7 6 输出:9 8 7 6 5 3 2 1 0 -4 解决方法:选择排序法 实现代码如下: #include &l ...
- 解决motools和jquery之间的冲突
在同一个页面需要同时使用motools和jquery,对于$,发生了冲突,以下是解决的办法. <head> <script src="./Scripts/lib/jquer ...
- JSON.parse与eval的区别
JSON.parse与eval和能将一个字符串解析成一个JSON对象,但还是有挺大区别. 测试代码 var A = "{ a: 1 , b : 'hello' }"; var B ...
- css_03之文本、浮动
1.字体属性:①字体格式:font-family:取值:“microsoft yahei”/Arial……:②字体大小:font-size:取值:pt/px:③字体加粗:font-weight:取值: ...
- css小技巧(1)
1.-webkit-overflow-scrolling: touch; 解决ios滑动时无缓冲问题 2.::-webkit-scrollbar 设置ios滑动时是否显示滚动条 3.::selecti ...
- 转载文章——Hadoop学习
转载地址:http://www.iteye.com/blogs/subjects/zy19982004?page=2 一.Hadoop社区版和发行版 社区版:我们把Apache社区一直开发的Hadoo ...
- 利用sphinx为python项目生成API文档
sphinx可以根据python的注释生成可以查找的api文档,简单记录了下步骤 1:安装 pip install -U Sphinx 2:在需要生成文档的.py文件目录下执行sphinx-apido ...