题目

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

  1. 输入:nums = [-1,0,1,2,-1,-4]
  2. 输出:[[-1,-1,2],[-1,0,1]]

已知条件

  • 0 <= nums.length <= 3000
  • -10^5 <= nums[i] <= 10^5

解题方案

本题要求取得所有和为0的三元组,并且不能重复,因此选择对数组排序后,通过双指针法遍历数组,寻找所有不重复的和为0的三元组。需要注意各层循环的条件以及左右指针移动的条件
循环条件:

  • 遍历指针由nums.begin()循环至nums.end()-3
  • 左右指针分别从i+1nums.end()-1开始,移动至重合

指针移动条件:

  • 遍历指针i>nums.begin()且与i-1处元素相等时i++
  • 左指针left>i+1且与left-1处值相等时left++
  • 右指针right<nums.end()-1且与right+1处的值相等时right--
  • 三个指针处的值和小于0时left++
  • 三个指针处的值和大于0时right--

该方法时间复杂度O(n^2)
C++代码:

  1. class Solution {
  2. public:
  3. vector<vector<int>> threeSum(vector<int>& nums) {
  4. vector<vector<int>> result;
  5. auto end = nums.end();
  6. auto start = nums.begin();
  7. vector<int>::iterator i, left, right;
  8. if (nums.size()<3) return result;
  9. sort(nums.begin(), nums.end());
  10. for (i=start; i!=end-2 && *i<1; ++i) {
  11. if (i>start && *i==*(i-1)) continue;
  12. left = i+1;
  13. right = end-1;
  14. while (left!=right) {
  15. if (left>i+1 && *left==*(left-1)){
  16. left++;
  17. continue;
  18. }
  19. if (right<end-1 && *right==*(right+1)){
  20. right--;
  21. continue;
  22. }
  23. if (*i+*left+*right<0) {
  24. left++;
  25. }
  26. else if (*i+*left+*right==0) {
  27. result.push_back({*i, *left, *right});
  28. left++;
  29. }
  30. else {
  31. right--;
  32. }
  33. }
  34. }
  35. return result;
  36. }
  37. };