给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解答:
第一种方法,排序预处理后,设置两个指针i,j 其中j = i + 1, i 遍历数组,剩下一个元素用二分法查找(此处使用lower_bound)
代码:
vector<vector<int>> threeSum(vector<int>& nums) {
sort( nums.begin(), nums.end());
vector<vector<int>> res;
if( nums.size() < 3 || nums[0] > 0 || nums[ nums.size() - 1] < 0)
return res;
set<vector<int>> result;
for( int i = 0; i < nums.size(); i++)
for( int j = i + 1; j < nums.size(); j++){
auto it = lower_bound( nums.begin() + j + 1, nums.end(), 0 - nums[i] - nums[j]) - nums.begin();
if( it < nums.size() && nums[it] + nums[i] + nums[j] == 0){
vector<int> temp{ nums[i], nums[j], nums[it]};
sort( temp.begin(), temp.end());
result.insert( temp);
}
}
for( auto it = result.begin(); it!= result.end(); it++)
res.push_back( *it);
return res;
}
解答:
方法二:排序预处理后,设置一个指针i 用来遍历,剩下两个元素,设置两个指针j 指向i+ 1, 和 k 指向 size() -1, 这两个指针从两侧向中间移动,寻找符合条件的元素。
代码:
vector<vector<int>> threeSum(vector<int>& nums) {
sort( nums.begin(), nums.end());
vector<vector<int>> res;
if( nums.size() < 3 || nums[0] > 0 || nums[ nums.size() - 1] < 0)
return res;
for( int i = 0; i < nums.size(); i++){
if( nums[i] > 0)
break;
if( i > 0 && nums[i] == nums[i-1])
continue;
int l = i + 1, r = nums.size() - 1;
while( l < r){
if( nums[i] + nums[l] + nums[r] == 0){
vector<int> temp = { nums[i] , nums[l] , nums[r]};
res.push_back( temp);
//去重
while( l<r && nums[l]==nums[l+1])l++;
while( l<r && nums[r]==nums[r-1])r--;
l++;
r--;
}
else if( nums[i] + nums[l] + nums[r] > 0)
r--;
else if( nums[i] + nums[l] + nums[r] < 0)
l++;
}
}
return res;
}