description:
15 | 3Sum | 21.8% | Medium |
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: 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] ]
my solution:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
std::sort(nums.begin(), nums.end());
std::vector<vector<int>> result;
int tempSum = 0, twoSum = 0;
int newBegin = 0;
int newEnd = nums.size() - 1;
for (int i = 0; i < nums.size(); ++i)
{
twoSum = -nums[i];
newBegin = i + 1;
newEnd = nums.size() - 1;
while(newBegin < newEnd) {
tempSum = nums[newBegin] + nums[newEnd];
if(tempSum < twoSum) {
newBegin++;
} else if(tempSum > twoSum) {
newEnd--;
} else {
std::vector<int> v;
v.push_back(nums[i]);
v.push_back(nums[newBegin]);
v.push_back(nums[newEnd]);
result.push_back(v);
while (newBegin < newEnd && nums[newBegin] == v[1]) newBegin++;
while (newBegin < newEnd && nums[newEnd] == v[2]) newEnd--;
}
}
while (i < nums.size() && nums[i + 1] == nums[i]) i++;
if(nums[i] > 0) break;
}
return result;
}
};
thought:
这道题的思路就是把三个数相加转化成两个数相加。
首先,对数组进行排序,其次从头到尾遍历数组,对每个数字取反都当成所求两个数字的和进行处理。
然后以该数字为界限,向后寻找两个数字,使之相加为该数字的负值。其中为了减小开销,两数字分别从头和尾部找起,这样做能把2维问题转化成1维问题。
最后的优化就是,跳过相同的数字,同时当遍历的数字大于0时,结束搜索,因为大于0时,剩下两个数字皆大于0,所以不用继续了。