1. 题目描述

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

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

示例:

  1. 给定数组 nums = [-1, 0, 1, 2, -1, -4],
  2. 满足要求的三元组集合为:
  3. [
  4. [-1, 0, 1],
  5. [-1, -1, 2]
  6. ]

2. 解题思路

这个题和之前的两数之和完全不一样,不过这里依旧可以使用双指针来实现。

我们在使用双指针时,往往数组都是有序的,这样才能不断缩小范围,所以我们要对已知数组进行排序。
(1)首先我们设置一个固定的数,然后在设置两个指针,左指针指向固定的数的后面那个值,右指针指向最后一个值,两个指针相向而行。
(2)每移动一次指针位置,就计算一下这两个指针与固定值的和是否为0,如果是,那么我们就得到一组符合条件的数组,如果不是0,就有一下两种情况:

  • 相加之和大于0,说明右侧值大了,右指针左移
  • 相加之和小于0,说明左侧值小了,左指针右移

(3)按照上边的步骤,将前len-2个值依次作为固定值,最终得到想要的结果。

因为我们需要三个值的和,所以我们无需最后两个值作为固定值,他们后面已经没有三个值可以进行计算了。

3. 代码实现

  1. /**
  2. * @param {number[]} nums
  3. * @return {number[][]}
  4. */
  5. var threeSum = function(nums) {
  6. let res = []
  7. let sum = 0
  8. // 将数组元素排序
  9. nums.sort((a,b) => {
  10. return a-b
  11. })
  12. const len =nums.length
  13. for(let i =0; i<len-2; i++){
  14. let j = i+1
  15. let k = len-1
  16. // 如果有重复数字就跳过
  17. if(i>0&& nums[i]===nums[i-1]){
  18. continue
  19. }
  20. while(j<k){
  21. // 三数之和小于0,左指针右移
  22. if(nums[i]+nums[j]+nums[k]<0){
  23. j++
  24. // 处理左指针元素重复的情况
  25. while(j<k&&nums[j]===nums[j-1]){
  26. j++
  27. }
  28. // 三数之和大于0,右指针左移
  29. }else if(nums[i]+nums[j]+nums[k]>0){
  30. k--
  31. // 处理右指针元素重复的情况
  32. while(j<k&&nums[k]===nums[k+1]){
  33. k--
  34. }
  35. }else{
  36. // 储存符合条件的结果
  37. res.push([nums[i],nums[j],nums[k]])
  38. j++
  39. k--
  40. while(j<k&&nums[j]===nums[j-1]){
  41. j++
  42. }
  43. while(j<k&&nums[k]===nums[k+1]){
  44. k--
  45. }
  46. }
  47. }
  48. }
  49. return res
  50. };

4. 提交结果

15. 三数之和 - 图1