1、背景介绍
给你一个包含 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] 输出:[]
2、解题思路
1、首先暴力枚举每一个数组元素,得到a[i],剩下的问题就是在数组中再找出两个数使其和为-a[i]。那么三数之和就转化成了两数之和,可以使用双指针算法。
2.1 证明双指针算法剪枝的合理性
在对一个数组排序后,根据a[l]和a[r]的和sum和目的值的大小关系,来移动左指针或者右指针,肯定不会排除可能解。
2.2如何去重
数组中可能出现重复的内容,去重从两个层面展开:
- 暴力枚举时
暴力枚举时,遇到和已经遍历过的元素值相等的元素时,选择跳过; - 双指针移动时
sum = a[i] + a[l] + a[r],其中a[i]已经不会重复,只要a[l]也不重复,就可以完全去重。
3、源码分享
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
vector<vector<int>> ret;
int preid = -1;
sort(nums.begin(),nums.end());
for(int i = 0; i < n; ++i){
if(preid != -1 && nums[preid] == nums[i]) continue;
int l = i + 1, r = n - 1;
while(l < r){
int sum = nums[i] + nums[l] +nums[r];
if(sum == 0){
ret.push_back({nums[i],nums[l],nums[r]});
int v = nums[l];
while(l < r && nums[l] == v) l++;
}else if(sum < 0){
l++;
}else{
r--;
}
}
preid = i;
}
return ret;
}
};
以上内容,如有争议之处,请不吝指出。
|