给你一个包含n
个整数的数组nums
,判断nums
中是否存在三个元素a,b,c,使得a + b + c = 0?请你找出所有和为0且不重复的三元组。
注意:答案中不可以包含重复的三元组。
提示:
- 0 <= nums.length <= 3000
- -10^5 <= nums[i] <= 10^5
15.三数之和
又到了爷最爱的去重环节
感觉提到去重就离不开排序,让这些蛇鼠一窝相同的元素放在一起,会比较好处理。
首先遍历第一个元素,如果第一个元素就大于0,那么后续肯定无法组合出和为0的数组,直接返回答案就行。
为了去重,如果已经开始列举第一个元素了,且和之前列举的相同,则continue。
然后开始求第二、三个元素,弄两个指针left和right(小黎这里直接用的j和k),初始化left为第一个元素的后一个指针,right为数组的最后一个。
由于这里对第二、三个元素的查找是并列的,所以从两端向中间找。如果当前加和大了,就左移right;如果小了,就右移left。所以在进入第二重循环前定义right,并且在第二重循环中right的值只减不增。当left和right重合的时候,~就说明我们回不去了~~就说明对于当前的第一个元素,已经没有更多的解了,直接break即可。
要注意,这里对于第二个元素也是有去重的,和第一个元素的去重思路相同,不再赘述啦。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| class Solution { public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> ans; if(nums.empty() || nums.size() < 3){ return ans; } sort(nums.begin(), nums.end()); int n = nums.size(); for(int i = 0; i < n; ++i){ if(nums[i] > 0){ return ans; } if(i > 0 && nums[i] == nums[i - 1]){ continue; } int k = n - 1; for(int j = i + 1; j < n; ++j){ if(j > i + 1 && nums[j] == nums[j - 1]){ continue; } while(j < k && nums[i] + nums[j] + nums[k] > 0){ k--; } if(j == k){ break; }else if(nums[i] + nums[j] + nums[k] == 0){ ans.push_back({nums[i], nums[j], nums[k]}); } }
} return ans; } };
|