15. 三数之和
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
**注意:**答案中不可以包含重复的三元组。
思路分析
双指针法: 两个循环 ,这个方法我们需要对数组进行排序。外层循环遍历给定的数组,搜集第一个元素。内层循环 left 和 right 指针缩小范围的同时,收集另外两个元素,因为答案不能包含重复的三元组,所以我们需要对满足条件的三元组进行去重。
如何对 left 和 right 进行初始化。
int left =0 , right = 0;
for(int i=0 ;i<nums.size() ; i++ ){
left = i+1;
right = nums.size()-1;
}
排序之后,如果三个数的和小于 0 ,说明三数相加太小,left ++ 。如果三个数的和大于0 right–。
当三个数之和 == 0 时。对结果集进行收集。
去重操作
我们需要对三个数进行去重 ,每当我们收集一个结果集之后 ,都要和之前的值进行比较 。
外层的 i (第一个元素) 判断 nums[i-1] == nums; 相等就继续循环
内层的 循环 nums[left +1] == nums[left] , nums[right-1] == nums[right] ,相等就跳过。不相等就收集
完整代码实现:
vector<vector<int>> threeSum(vector<int>& nums) {
//双指针法
vector<vector<int>>ret;
if(nums.size() == 0) return ret;
sort(nums.begin() ,nums.end()); // 排序,升序
int left =0 , right = 0;
int temp = 0;
for(int i=0; i<nums.size()-2 ;i++){
if(nums[i]> 0 ) break;
left = i+1;
right = nums.size()-1;
//对第一个数进行去重
if( i>0 && nums[i]==nums[i-1]) continue;
while(left <right){
temp = nums[i] + nums[left] + nums[right]; //三数相加
//对范围进行压缩
if( temp < 0 ){
left++;
}else if(temp >0){
right--;
}else{ //等于0
//收集一个结果集{
ret.push_back(vector<int>{nums[i] ,nums[left] ,nums[right]});
//去重操作
while(left < right && nums[left + 1] == nums[left]) left++;
while(left < right && nums[right - 1] == nums[right]) right--;
right--;
left++;
}
}
}
return ret;
}