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] ]====================================================================================
题目链接: https://leetcode.com/problems/3sum/
题目大意:给定一个数组,求数组中三个数(不重复)能构成 和为0的所有集合(集合内数值从小到大排序,而且集合不能重复)。
思路:最直接的做法就是三重循环扫过去,遇到符合条件的集合就存下来,然后再用一个算法筛除重复的集合,很强很暴力,但是时间复杂度为O(N^3)。很不幸超时了。能不能有一个更快的方法呢?
先对给定的数组从小到大排个序,我们先确定集合内最小的那个数nums[i],其中 0 < i < n - 2,然后我们用一个左指针left(下标为i+1,,即集合最小值的下一个),一个右指针right(下标为n-1,即最大一个值),当三个数之和小于0时,左指针右移一位;但三个数之和大于0时,右指针左移一位;当三个数之和等于0时,记录下当前值,左指针右移,右指针左移,以此类推。
注意点:当数组中出现多个同样数值,要注意除重,除重步骤代码有标出。
附上代码:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector < vector <int> > ans ;
ans.clear() ;
int n = nums.size() ;
sort ( nums.begin() , nums.end() ) ;
for ( int i = 0 ; i < n - 2 ; i ++ )
{
if ( i && nums[i] == nums[i-1] )//除重
continue ;
int left = i + 1 , right = n - 1 ;
while ( left < right )
{
int sum = nums[left] + nums[right] + nums[i] ;
if ( ! sum )
{
ans.push_back ( { nums[i] , nums[left] , nums[right] } ) ;
while ( ++ left < right && nums[left] == nums[left-1] ) ;//除重
while ( left < -- right && nums[right] == nums[right+1] ) ;//除重
}
else if ( sum < 0 )
left ++ ;
else
right -- ;
}
}
return ans ;
}
};