算法挑战29: 三数之和

2 阅读1分钟

题目:

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

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

思路:

有了两数之和的经验,我们可以用一个for循环里面嵌套一个求两数之和的思路

外层for循环永远遍历三元组的第一个元素

剩下两个元素只要和是第一个元素的相反数就可以了

注意几点细节:

1.如果某个元素开始,大于0了,那后面就不用算了,必定不能和为零,之间跳出此次循环就可以了

2.如果这个元素跟上一个元素一样的话,就跳过就行

3.for循环的元素重复了需要跳, 内部两个元素重复了也需要跳

代码:

var threeSum = function (nums) {
    let res = [];
    //排序
    nums.sort((a, b) => a - b);
    let len = nums.length;

    //遍历第一个元素
    for (let i = 0; i < len - 2; i++) {
        //如果某个元素开始,大于0了,那后面就不用算了,必须大于0
        if (nums[i] > 0) {
            break;
        }
        //连续重复元素
        if (nums[i] === nums[i - 1] && i > 0) {
            continue;
        }
        let left = i + 1;
        let right = len - 1;
        //二数之和
        while (left < right) {
            let sum = nums[left] + nums[right] + nums[i];
            if (sum > 0) {
                right--;
            } else if (sum < 0) {
                left++;
            } else {
                res.push([nums[i], nums[left], nums[right]]);
                left++;
                     //连续重复元素
                while (left < right && nums[left] === nums[left - 1]) {
                    left++;
                }
                right--;
                     //连续重复元素
                while (left < right && nums[right] === nums[right + 1]) {
                    right--;
                }
            }
        }
    }
    return res;
};