leetcode15-三数之和

leetcode 15
leetcode15-三数之和_第1张图片

思路

时间复杂度:O(n2) 空间复杂度:O(logn)+O(k)

本题主要考虑使用双指针法解答,遍历i的时候i固定,然后定义两个指针left和right,通过移动left和right来使得总和相加为0,但是有个**前提是需要先将数组进行排序。排序完以后的数组,如果总和发现过小那么我们左指针右移动,因为越向右值越大,如果总和过大,那么右指针左移,找到总和为0,把这三个元素放入答案中。
在不断移动的过程中很重要的一个细节:
去重**,因为题目中有说明不可以包含重复的三元组,就是当已经出现过例如[-1,-1,2]这个答案以后,后面不能再出现这个答案,我们对于i,left,right都需要进行去重,i循环的时候如果i的前一个数和当前数是相等我们就要continue,因为如果当前的值和之前的值一样的话,那么后续遍历过的元素,在前一个值那里已经完全遍历过一遍,所以不需要再进行遍历,同样left如果和前一个元素一样,right和后一个元素一样时也是直接continue
leetcode15-三数之和_第2张图片
图片来自代码随想录

实现

var threeSum = function (nums) {
    // 排序
    nums.sort((a, b) => a - b)
    let result = [];
    for (let i = 0; i < nums.length - 2; i++) {
        if (nums[i] > 0) return result;
        // 去重,如果下一个遍历的元素和上一个元素相等,那么后续的元素其实是已经遍历过了
        if (i > 0 && nums[i] === nums[i - 1]) {
            continue;
        }
        let left = i + 1, right = nums.length - 1;
        while (left < right) {
            // 去重
            if (left > i + 1 && nums[left] === nums[left - 1]) {
                left++;
                continue
            }
            if (right < nums.length - 1 && nums[right] === nums[right + 1]) {
                right--;
                continue;
            }
            let sum = nums[left] + nums[right] + nums[i]
            if (sum === 0) {
                // 目标值
                result.push([nums[i], nums[left], nums[right]])
                left++
            } else if (sum < 0) {
                // 和小了,那么需要把left右移,让总体值变大
                left++;
            } else {
                // 和大了
                right--;
            }
        }
    }
    return result;
};

你可能感兴趣的:(算法小课堂,数据结构,leetcode,算法)