一、题目描述:15. 三数之和(中等)
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解题思路
1、先对数组进行升序排序。
2、从左到又开始遍历i,由于三个元素a+b+c=0;则,-a = (b+c);也就是说,对每个下标为i的数字,只要找到i右边所有和为-a的组合就可以,由于数组是升序排序的,所有使用双指针(下标)解法,定义双指针left = i+1,right=len-1;(注意:1)遍历的时候如果nums[i]==nims[i-]则continue,因为同一个数字,找到的组合是相同的,没必要再找了。2)当nums[i] 大于0的时候也没必要找了,因为此时i右边的数字都是大于0的,所有i和i右边的数字的组合,a+b+c恒大于0。此时break跳出循环就可以)
3、当left<right的时候,如果nums[left] + nums[right] 小于-a的话则left++(为了保证不会有重复组合,同时如果nums[left-1] == nums[left]的话,继续left++,left的数字和前一个数字不一致为止)。
4、当left<right的时候,如果nums[left] + nums[right] 大于-a的话则right--(为了保证不会有重复组合,同时如果nums[right] == nums[right+1]的话,继续right--,right的数字和后一个数字不一致为止)
5、如果nums[left] + nums[right] == -a,说明找到了a+b+c =0 的组合,将组合保存,left++,right--。(同时为了去重,当nums[left] == nums[left-1]的时候,继续left++。nums[right] == nums[left+1]的时候,继续right--。因为如果当前数字已经找过了组合,后面数字相同的话找到的组合是一样的,再找的话就是重复的)
三、代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
int len = nums.size();
vector<vector<int>> saveArray;
for(int i = 0 ;i < len-1;i++)
{
if(i >0 && nums[i]== nums[i-1])
continue;
if(nums[i] > 0)
break;
int left = i+1,right = len - 1;
int tmp = -1 * nums[i];
while(left < right)
{
int sum_t = nums[left] + nums[right];
if(sum_t < tmp)
{
left++;
while(left>0 && left< len&& nums[left-1] == nums[left])
left++;
}
else if(sum_t > tmp)
{
right--;
while((right<len-1 && right>=0 && nums[right] == nums[right+1]))
right--;
}
else
{
/*
cout<<"i="<<i<<endl;
cout<<"nums[i]="<<nums[i]<<endl;
cout<<"left="<<left<<endl;
cout<<"right="<<right<<endl;
cout<<"nums[left]="<<nums[left]<<endl;
cout<<"nums[right]="<<nums[right]<<endl;
*/
vector<int> save;
save.push_back(nums[i]);
save.push_back(nums[left]);
save.push_back(nums[right]);
left++;
right--;
while(left>0 && left< right&& nums[left-1] == nums[left])
left++;
while((right<len-1 && right>left && nums[right] == nums[right+1]))
right--;
saveArray.push_back(save);
}
}
}
return saveArray;
}
};