题目:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
class Solution {
public:
//时间复杂度是O(nlogn)+O(n^2),所以总的时间复杂度是O(n^2),空间复杂度是O(1)
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > res;
if (nums.size() < 3) return res;
vector<int> oneTriplet(3);
//排序
sort(nums.begin(), nums.end());
//for循环遍历数组,在其后用首尾指针找和为-nums[i]的两个元素,注意去重
for (int i = 0; i < nums.size() - 2; ++i){
if (i != 0 && nums[i] == nums[i - 1]) continue;//去重
int target = -nums[i];
int left = i + 1;
int right = nums.size() - 1;
while (left < right){
if (left != i + 1 && nums[left] == nums[left - 1]){
++left;
continue;
}
if (right != nums.size() - 1 && nums[right] == nums[right + 1]){
--right;
continue;
}
if (nums[left] + nums[right] == target){
oneTriplet[0] = nums[i];
oneTriplet[1] = nums[left];
oneTriplet[2] = nums[right];
res.push_back(oneTriplet);
++left;
}
else if (nums[left] + nums[right] < target) ++left;
else --right;
}
}
return res;
}
};
下面是用hash的方法找2sum,会TLE
class Solution {
public:
//时间复杂度是O(n*n*logn),空间复杂度是O(n)
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int> > res;
if (nums.size() < 3) return res;
//排序
sort(nums.begin(), nums.end());
//for循环遍历数组,找2sum(hash),注意去重
for (int i = 0; i < nums.size() - 2; ++i){
if (i != 0 && nums[i] == nums[i - 1]) continue;//去重
int target = -nums[i];
set<pair<int, int> > lastTwo;
if (found2Sum(nums, i + 1, target, lastTwo)){
vector<int> tmp(3);
for (set<pair<int, int> >::iterator iter = lastTwo.begin(); iter != lastTwo.end(); ++iter){
tmp[0] = nums[i];
tmp[1] = iter->first;
tmp[2] = iter->second;
res.push_back(tmp);
}
}
}
return res;
}
private:
bool found2Sum(vector<int> &nums, int start, int target, set<pair<int, int> > &lastTwo){//为了得到无重复的二元组,所以使用set
if (start >= nums.size() - 1) return false;
set<int> hashSet;
hashSet.insert(nums[start]);
for (int i = start + 1; i < nums.size(); ++i){
if (hashSet.count(target - nums[i])){//找到
lastTwo.insert(make_pair(target - nums[i], nums[i]));
}
hashSet.insert(nums[i]);
}
return lastTwo.size() ? true : false;
}
};
注:
1.本题和2sum不同,2sum要求输出下标,所以不能使用先对数组排序在使用首尾指针来查找,hash更合适。本题要求输出元素值,所以排序+首尾指针更合适(时间和空间效率都更高)
2.注意去重,而且两层都要去重。