15. 3Sum
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]
]
题意:
给定一个含有n个整数的数组,在给定的数组中,找到三个数,使其之和等于0。
注意:答案要求三个数字按照非递减排列,而且不包含重复的。
思路:
这道题的思路和之前的[leetcode] 167. Two Sum II - Input array is sorted 差不多,用两个指针pre和tail从这个数后面的两边往中间查找。但是需要先升序排序,然后用第一重for循环确定第一个数字,然后在while循环里(也就是第二重循环),第二、第三个数字分别从两端往中间扫。当这三个数之和等于0的时候,记录一下,当之和大于0的时候,tail左移,而当之和小于0的时候,pre右移,直到pre和tail相遇。这个其实就是在Two Sum外层加1层循环,因此时间复杂度是排序的O(nlogn)加上O(n2),即O(n2)。
特别注意:由于要求不包含重复元素,因此在选择第一个数字的时候以及后面两个指针查找时,需要跳过重复元素。代码如下:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
set<vector<int>> tempRes;//防止出现重复的三元组元素
if (nums.size() < 3)
return res;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size() - 2; i++)
{
if (nums[i] > 0)//按数组递增排序,第i个大于0,后面的数一定大于零
break;
if (i>0 && nums[i] == nums[i - 1])continue;//排序后如果nums[i] == nums[i - 1],肯定会出现和前一个i重复的三元组,跳过
int pre = i + 1;
int tail = nums.size() - 1;
while (pre<tail)
{
vector<int> vals;
int sum = nums[i] + nums[pre] + nums[tail];
if (sum == 0)
{
vals.push_back(nums[i]);
vals.push_back(nums[pre]);
vals.push_back(nums[tail]);
tempRes.insert(vals);
pre++;
tail--;
while (pre < tail&&nums[pre] == nums[pre - 1]) pre++;//因为同一个nums[i],如果nums[pre] == nums[pre - 1],则取出来的三元组肯定是重复的,所以直接把pre向后移动,跳过,然后再计算
while (pre < tail&&nums[tail] == nums[tail + 1]) tail--;//因为同一个nums[i],如果nums[tail] == nums[tail + 1],则取出来的三元组肯定是重复的,所以直接把tail向前移动,跳过,然后再计算
}
else if (sum < 0)
{
pre++;
}
else
tail--;
}
}
for (auto s : tempRes)
{
res.push_back(s);
}
return res;
}
};