题目描述:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路分析:
面试中常常出现的3sum问题,和2sum是比较类似的。但这里由于是三个数的和为0,因此首先需要固定一个数,再在其后续的序列中利用2sum的方法。由于题目要求不可包含重复的三元组,因此需要进行一些过滤。首先对数组进行排序,判断当前元素是否大于0,若大于0,则不可能与后续的元素组成三元组,直接退出。若当前的元素与前一个元素相等,表示重复,跳过本轮循环。此外,在twoSum函数中,也需要进行判断,若当前left值与前一位相等,则重复,跳过;同理当前right值与后一位相等,则重复,跳过。算法复杂度为O(n^2)。
代码:
1 class Solution { 2 public: 3 void twoSum(vector<vector<int>>&res, vector<int>& nums, int cur) 4 { 5 int left = cur+1; 6 int right = nums.size()-1; 7 while(left<right && left>cur && right<nums.size()) 8 { 9 int sum = nums[left]+nums[cur]+nums[right]; 10 if(sum > 0) 11 right--; 12 else if(sum < 0) 13 left++; 14 else 15 { 16 if(left==cur+1 || right==nums.size()-1) 17 { 18 res.push_back(vector<int>{nums[cur], nums[left], nums[right]}); 19 left++; 20 right--; 21 } 22 else if(nums[left]==nums[left-1]) 23 left++; 24 else if(nums[right] == nums[right+1]) 25 right--; 26 else 27 { 28 res.push_back(vector<int>{nums[cur], nums[left], nums[right]}); 29 left++; 30 right--; 31 } 32 } 33 } 34 } 35 vector<vector<int>> threeSum(vector<int>& nums) { 36 vector<vector<int>> res; 37 if(nums.size()<3) 38 return res; 39 sort(nums.begin(), nums.end()); 40 for(int i=0; i<nums.size(); i++) 41 { 42 if(nums[i]>0) 43 break; 44 if(i>0 && nums[i]==nums[i-1]) 45 continue; 46 twoSum(res, nums, i); 47 } 48 return res; 49 } 50 };