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

    最简单的方法是把数组 nums 所有可以三元组的可能都列出来进行循环把和为 0 得取出来并进行去重。
    这样的时间复杂度是

    更优的解法是先进行排序,再使用双指针的办法进行判断三数之和。这样的时间复杂度是 三数之和 - 图1

    1. let nums = [-1, 0, 1, 2, -1, -4, 1, 2]; // [[-4, 2, 2], [-1, -1, 2], [-1, 0, 1]]
    2. var threeSum = function (nums) {
    3. let resArr = [];
    4. // 数组至少要有三个元素才能进行
    5. if (nums.length < 3) return [];
    6. // 让数组排序,成为一个升序数组 [ -4, -1, -1, 0, 1, 1, 2, 2 ]
    7. nums = nums.sort((a, b) => a - b);
    8. for (let i = 0; i < nums.length; i++) {
    9. // 开始遍历或当前遍历的数组元素与上一次遍历的数组元素不一样时
    10. if (i == 0 || nums[i] != nums[i - 1]) {
    11. // 元素大于 0 时,左右指针的元素都大于 0,无法三数之和等于 0
    12. if (nums[i] > 0) {
    13. break;
    14. }
    15. // 左指针为当前元素的下个元素,右指针为数组最后一个元素,得出它们对应的索引
    16. let left = i + 1,
    17. right = nums.length - 1;
    18. // 左指针的索引一定要比右指针的索引小
    19. while (left < right) {
    20. // 当前元素、左指针元素、右指针元素三数之和为 0
    21. if (nums[i] + nums[left] + nums[right] == 0) {
    22. resArr.push([nums[i], nums[left], nums[right]]);
    23. left++;
    24. // 左指针右移,直到左指针与前一个左指针的元素不一样或与右指针索引相同
    25. while (left < right && nums[left] == nums[left - 1]) {
    26. left++;
    27. }
    28. // 三数之和小于 0, 需要多一点的正数,左指针向右移动
    29. } else if (nums[i] + nums[left] + nums[right] < 0) {
    30. left++;
    31. // 左指针右移,直到左指针与前一个左指针的元素不一样或与右指针索引相同
    32. while (left < right && nums[left] == nums[left - 1]) {
    33. left++;
    34. }
    35. // 三数之和大于 0, 需要多一点的负数,右指针向左移动
    36. } else if (nums[i] + nums[left] + nums[right] > 0) {
    37. right--;
    38. // 右指针左移,直到右指针与前一个右指针的元素不一样或与左指针索引相同
    39. while (left < right && nums[right] == nums[right + 1]) {
    40. right--;
    41. }
    42. }
    43. }
    44. }
    45. }
    46. return resArr;
    47. };
    48. console.log(threeSum(nums));