问题描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解题报告
最为暴力的方式:直接三重循环枚举元素 a
、b
、c
,因为每个元素只能使用一次,所以在整个数组中枚举 a
,然后在 a
之后的元素中枚举 b
, 然后在 b
之后枚举 c
。这样人为定义枚举次序,才不会出现重复枚举,避免重复运算。
但是这样的暴力枚举是存在重复计算的。枚举 a
之后,如果 a
的大小已经大于 target
那么后面但凡 b
和 c
大于 0
, 都不可能是正确的答案。所以最好的解决方案是先对数组排序。
当枚举了 a
之后,我们需要在 a
之后的元素中枚举 b
和 c
,使 b+c
等于 target-a
,这里我们可以在 O(n)
的复杂度内达到要求。由于数组是有序的,我们只要将 b
初始化为 a
后面的那个元素,将 c
初始化为最后一个元素,那么我们就可以在 O(n)
的时间内判断是否有 b
和 c
使 b+c
等于 target-a
。
实现代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>ans;
if(nums.size()<=2)return ans;
sort(nums.begin(), nums.end());
int i,j,sum;
for(int k=0;k<nums.size()-2;k++){
if(nums[k]>0) break;
if(k&&nums[k]==nums[k-1])continue;
i=k+1;
j=nums.size()-1;
while(i<j){
sum=nums[k]+nums[i]+nums[j];
if(sum>0)while(i < j && nums[j] == nums[--j]);
else if(sum<0)while(i < j && nums[i] == nums[++i]);
else{
ans.push_back({nums[k],nums[i],nums[j]});
while(i < j && nums[i] == nums[++i]);
while(i < j && nums[j] == nums[--j]);
}
}
}
return ans;
}
};
参考文献
[1] Leetcode 15.三数之和