三数之和
题目类型:数组
题目来源: leetcode传送门
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
**注意:**答案中不可以包含重复的三元组。
示例1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例2:
···
输入:nums = []
输出:[]
···
示例3:
···
输入:nums = [0]
输出:[]
···
提示:
* 0 <= nums.length <= 3000
* -10^5^ <= nums[i] <= 10^5^
方法一:
最暴力的方法,三重循环,但是需要注意的细节是,由于答案不能重复,也就是避免[-1,0,1]和[-1,1,0]这种情况出现,要做的首先就是排序了,排序之后考虑如何避免这种情况的出现。如果第p次第一层循环变量为i,那么在第p+1次,第一层的循环变量i+1,这时如果排好序的nums[i]和nums[i+1]相等,则第二三层循环就可以仍然在上一次得到答案的状态下再次得到答案,自然就会出现重复的答案。需要做的就是在第p+1次时的vector中的元素与第p次的元素不能相同。这样就可以完成去重的过程了。代码如下(由于是O(n3)的,所以超时了):
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > ans(0);
vector<int> t_vector(0);
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); i ++)
{
if(!(i == 0 || nums[i] != nums[i-1]))
continue;
for(int j = i + 1; j < nums.size(); j ++)
{
if(!(j == i+1 || nums[j] != nums[j-1]))
continue;
for(int k = j + 1; k < nums.size(); k ++)
{
if(!(k == j+1 || nums[k] != nums[k-1]))
continue;
if(nums[i] + nums[j] + nums[k] == 0)
{
t_vector.clear();
t_vector.push_back(nums[i]);
t_vector.push_back(nums[j]);
t_vector.push_back(nums[k]);
ans.push_back(t_vector);
}
}
}
}
return ans;
}
方法二:
采用双指针的做法,第一重循环不变,在第一重循环内部,j指向i+1,k指向nums.size()-1,如果nums[i]+nums[j]+nums[k]等于0,则记录,并且向右移动j指针,如果大于0,则向左移动k指针,如果小于0,则向右移动j指针,这里的移动都要满足移动之后与上一次指的位置的指不同。
代码如下:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > ans(0);
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); ++i)
{
if(!(i == 0 || nums[i] != nums[i-1]))
continue;
int j = i + 1;
int k = nums.size() - 1;
int tar = 0 - nums[i];
while(j < k)
{
if(nums[j] + nums[k] == tar)
{
ans.push_back({nums[i], nums[j], nums[k]});
while(j < k && nums[j+1] == nums[j])
++j;
++j;
}
else if(nums[j] + nums[k] > tar)
{
while(j < k && nums[k-1] == nums[k])
--k;
--k;
}
else if(nums[j] + nums[k] < tar)
{
while(j < k && nums[j+1] == nums[j])
++j;
++j;
}
}
}
return ans;
}
}
作答加上写博客,一共用了接近1.5个小时,还是太慢了,还需要继续练习呀!!!