LeetCode(15):三数之和
Medium!
题目描述:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解题思路:
这道题让我们求三数之和,比之前那道Two Sum要复杂一些,考虑过先fix一个数,然后另外两个数使用Two Sum那种HashMap的解法,但是会有重复结果出现,就算使用set来去除重复也不行,会TLE,看来此题并不是考我们Two Sum的解法。那么我们来分析一下这道题的特点,要我们找出三个数且和为0,那么除了三个数全是0的情况之外,肯定会有负数和正数,我们还是要先fix一个数,然后去找另外两个数,我们只要找到两个数且和为第一个fix数的相反数就行了,既然另外两个数不能使用Two Sum的那种解法来找,如果能更有效的定位呢?我们肯定不希望遍历所有两个数的组合吧,所以如果数组是有序的,那么我们就可以用双指针以线性时间复杂度来遍历所有满足题意的两个数的组合。
我们对原数组进行排序,然后开始遍历排序后的数组,这里注意不是遍历到最后一个停止,而是遍历到倒数第三个就可以停止了。这里我们可以先做个剪枝优化,就是当遍历到正数的时候就break,为啥呢,因为我们的数组现在是有序的了,如果第一个要fix的数就是正数了,那么后面的数字就都是正数,就永远不会出现和为0的情况了。然后我们还要加上重复就跳过的处理,处理方法是从第二个数开始,如果和前面的数字相等,就跳过,因为我们不想把相同的数字fix两次。对于遍历到的数,用0减去这个fix的数得到一个target,然后只需要再找到两个数之和等于target即可。我们用两个指针分别指向fix数字之后开始的数组首尾两个数,如果两个数和正好为target,则将这两个数和fix的数一起存入结果中。然后就是跳过重复数字的步骤了,两个指针都需要检测重复数字。如果两数之和小于target,则我们将左边那个指针i右移一位,使得指向的数字增大一些。同理,如果两数之和大于target,则我们将右边那个指针j左移一位,使得指向的数字减小一些,代码如下:
C++参考答案一:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int k = ; k < nums.size(); ++k) {
if (nums[k] > ) break;
if (k > && nums[k] == nums[k - ]) continue;
int target = - nums[k];
int i = k + , j = 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;
}
};
或者我们也可以利用set的不能包含重复项的特点来防止重复项的产生,那么我们就不需要检测数字是否被fix过两次,不过个人觉得还是前面那种解法更好一些,参见代码如下:
C++参考答案二:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
set<vector<int>> res;
sort(nums.begin(), nums.end());
for (int k = ; k < nums.size(); ++k) {
if (nums[k] > ) break;
int target = - nums[k];
int i = k + , j = 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());
}
};
知识点补充:
set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值。使用的时候要包含头文件“#include<set>”。
set的各成员函数列表如下:
1. begin()--返回指向第一个元素的迭代器
2. clear()--清除所有元素
3. count()--返回某个值元素的个数
4. empty()--如果集合为空,返回true
5. end()--返回指向最后一个元素的迭代器
6. equal_range()--返回集合中与给定值相等的上下限的两个迭代器
7. erase()--删除集合中的元素
8. find()--返回一个指向被查找到元素的迭代器
9. get_allocator()--返回集合的分配器
10. insert()--在集合中插入元素
11. lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
12. key_comp()--返回一个用于元素间值比较的函数
13. max_size()--返回集合能容纳的元素的最大限值
14. rbegin()--返回指向集合中最后一个元素的反向迭代器
15. rend()--返回指向集合中第一个元素的反向迭代器
16. size()--集合中元素的数目
17. swap()--交换两个集合变量
18. upper_bound()--返回大于某个值元素的迭代器
19. value_comp()--返回一个用于比较元素间的值的函数
#include<set>
#include<iostream>
using namespace std;
int main()
{
int i;
int arr[] = {,,,,};
set<int> iset(arr,arr+); iset.insert();
cout<<"size:"<<iset.size()<<endl;
cout<<"3 count = "<<iset.count()<<endl;
iset.erase(); set<int>::iterator ite1 = iset.begin();
set<int>::iterator ite2 = iset.end();
for(;ite1!=ite2;ite1++)
{
cout<<*ite1;
}
cout<<endl; ite1 = iset.find();
if(ite1!=iset.end())
cout<<"3 found"<<endl; ite1 = iset.find();
if(ite1!=iset.end())
cout<<"1 not found"<<endl;
}
LeetCode(15):三数之和的更多相关文章
- LeetCode 15. 三数之和(3Sum)
15. 三数之和 15. 3Sum 题目描述 Given an array nums of n integers, are there elements a, b, c in nums such th ...
- Java实现 LeetCode 15 三数之和
15. 三数之和 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以 ...
- 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 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复 ...
- [Leetcode 15]三数之和 3 Sum
[题目] Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? ...
- [LeetCode]15. 三数之和(数组)(双指针)
题目 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三 ...
- [LeetCode] 15. 三数之和
题目链接:https://leetcode-cn.com/problems/3sum/ 题目描述: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a ...
- LeetCode:三数之和【15】
LeetCode:三数之和[15] 题目描述 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的 ...
- 代码随想录第七天| 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和
第一题454.四数相加II 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, ...
- leetcode题目15.三数之和(中等)
题目描述: 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重 ...
随机推荐
- P3114 [USACO15JAN]踩踏Stampede
题目链接 我一开始看错题了,看成每秒走\(c_i\)个单位了,于是样例答案就变成了3..害我调好久,还以为样例错了 对于每头奶牛,我们求出它经过\(y\)轴的时间段,然后离散化一下,将奶牛按照从低到高 ...
- 【BZOJ3139】[HNOI2013]比赛(搜索)
[BZOJ3139][HNOI2013]比赛(搜索) 题面 BZOJ 洛谷 题解 双倍经验
- 解决 Previous operation has not finihsed; run ‘cleanup’ if it was interrupted Please execute the ‘Cleanup’ command
更新时遇到这个问题,解决方法如下: 把根目录下的.svn目录删除掉,再checkout,然后就会出现下面的加version的action. 疯吻IT
- Atcoder Grand 012 C - Tautonym Puzzle
题意: 构造一个字符串,使得这个字符串有只有n个形如AA这样的子序列. 神TM构造题不会做,, 我们构造一个长度为2*m的字符串,前m个是一个1-m的排列,后m个就是按顺序1-m. 这样这个串里符合要 ...
- C/C++如何整行读入字符串?
在写代码的过程中,经常要一行一行的读入字符串进行处理,这里我总结了一些方法,供大家参考. 方法一:scanf()读入char[] 使用方法: ]; scanf("%[^\n]",& ...
- Eclipse 报 "The builder launch configuration could not be found" 错误
Eclipse 报 "The builder launch configuration could not be found" 错误的解决办法 标签: eclipseEclipse ...
- UiAutomator2.0入门
总是听说UiAutomator这个框架,但从来没有使用过.找了篇入门,实践一下.实践之后感觉,uiautomator写测试代码,还是有点费劲.接口名比较多,比较长.网易的atx里使用的uiautoma ...
- PHP多条件模糊查询
所使用的方法:$sqlArr=array();array_push();implode(); 原理, 一.建立sql语句前半句,并且建立一个空数组. 二.根据条件是否为空来判断是否向数组中添加元素.如 ...
- linux ------ 使用 TFTP 在两个主机之前传输文件
TFTP是用来下载远程文件的最简单网络协议,它是基于UDP协议而实现.嵌入式linux的tftp开发环境包括两个方面:一是linux服务器端的tftp-server支持,二是嵌入式目标系统的tftp- ...
- CM记录-CDH大数据平台实施经验总结2016(转载)
CDH大数据平台实施经验总结2016(转载) 2016年负责实施了一个生产环境的大数据平台,用的CDH平台+docker容器的方式,过了快半年了,现在把总结发出来. 1. 平台规划注意事项 1.1 业 ...