[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 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] 15. 3Sum 三数之和的更多相关文章
- [leetcode]15. 3Sum三数之和
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find ...
- 【LeetCode】15. 3Sum 三数之和
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 个人公众号:负雪明烛 本文关键词:3sum, 三数之和,题解,leetcode, 力扣,P ...
- leetCode 15. 3Sum (3数之和) 解题思路和方法
3Sum Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find ...
- 【LeetCode 15】三数之和
题目链接 [题解] 先把n个数字升序排个序. 然后枚举三元组最左边的那个数字是第i个数字. 之后用两个指针l,r移动来获取三元组的第2个和第3个数字. (初始值,l=i+1,r = n-1); 如果a ...
- [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、三数之和为0
题目等级:3Sum(Medium) 题目描述: Given an array nums of n integers, are there elements a, b, c in nums such t ...
- LeetCode 第15题-三数之和
1. 题目 2.题目分析与思路 3.思路 1. 题目 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且 ...
- LeeCode数组第15题三数之和
题目:三数之和 内容: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中 ...
- 【LeetCode每天一题】3Sum(三数之和)
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find ...
随机推荐
- Vue.js 源码分析(三) 基础篇 模板渲染 el、emplate、render属性详解
Vue有三个属性和模板有关,官网上是这样解释的: el ;提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标 template ;一个字符串模板作为 Vue 实例的标识使用.模板将会 ...
- C# 中如何深度复制某一个类型(备注:可能有 N 个类型需要复制)的对象?
如题,针对某一个特定的类型,深度复制,没有那么难,最起码可以手动赋值,但如果要针对 N 多类型深度复制,最简单的方法,是把这个对象序列化成 XML.JSON 或其它可以序列化的载体,然后再将这个载体反 ...
- Asp.NET Core Nginx Ocelot ForwardedHeaders X-Forwarded-For
ocelot在部署时我使用了nginx作为转发,并配置了https证书,但是发现ocelot不支持Forward host header. https://ocelot.readthedocs.io/ ...
- visa
- C# 处理接口返回的XML格式数据
using System.Xml; //引入命名空间 //模拟接口返回的数据 string str=@"<JZD_Message xmlns:xsd=""http: ...
- winform子窗口调用父窗口的控件及方法-一般调用
首先新建一个窗体应用程序,在项目属性中点击右键->添加->添加新项,选择Windows窗体->添加. 在Form1和Form2窗口中各添加一个按钮,并双击添加事件处理函数: ...
- Java 并发学习总结
目录 基础篇 进阶篇 并发编程的的三个概念(特性)? JMM(Java 内存模型) volatile 关键字 1. Java 内存模型(为什么要有 volatile) 2. volatile 原理 追 ...
- Celery 异步队列
Celery Celery是一个功能完备即插即用的异步任务队列系统.它适用于异步处理问题,当发送邮件.或者文件上传, 图像处理等等一些比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用 ...
- IOS之UIColor
转自:http://blog.csdn.net/wudizhukk/article/details/8607229 UIColor常见用法,废话少说 直接网上抄来记录下,凭空想还真有点想不起来,最近记 ...
- 【推荐】全球最全面的Telegram组群频道的集合网站 持续收集中
全球最全面的Telegram组群频道的集合网站 https://www.telegramgroup.org Telegram 组群频道分享 可搜索自己想找的组群频道 从小白到大神,一个 telegra ...