LeetCode 15. 三数之和

111 阅读1分钟

image.png

解析

解法1

  • 首先对数组进行排序,排序后固定一个数 nums[i],再使用左右指针指向nums[i]后面的两端,数字分别为 nums[l]和 nums[r],计算三个数的和 sum 判断是否满足为 0,满足则添加进结果集。
  • 因为已经排好顺序了
    • 如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环
  • 如果 nums[i]== nums[i-1],则说明该数字重复,会导致结果重复,所以应该跳过
  • 当 sum == 0 时
    • nums[l] == nums[l+1] 则会导致结果重复,应该跳过,l++
    • nums[r] == nums[r-1] 则会导致结果重复,应该跳过,r--
  • 时间复杂度:O(n^2),n为数组长度
/**
 * @param {number[]} nums
 * @return {number[][]}
 */
 // 双指针
var threeSum = function(nums) {
    let result = []
    let len = nums.length
    nums.sort((a,b) => a-b)
    if(len < 3){
        return result
    }
    for(let i = 0; i < len ; i++){
        // 因为前面已经排好序列了
        if(nums[i] > 0) break // 如果当前数字大于0,则三数之和一定大于0,所以结束循环
        // 当前数值和前一个一样的话  答案一定一样
        if(nums[i] === nums[i-1]) continue  //去重
        // 双指针
        let l = i + 1
        let r = len - 1
        // 双指针遍历
        while( l < r){
            //得出和
            let sum = nums[i] + nums[l] + nums[r]
            //相等的情况
            if(sum === 0){
                //加入到结果数组中
                result.push([nums[i],nums[l],nums[r]])
                //去重操作
                //如果左指针下一个和当前一样   肯定会重复
                while(l<r && nums[l] === nums[l+1]) l++
                //如果右指针前一个和当前一样   肯定会重复
                while(l<r && nums[r] === nums[r-1]) r--
                l++
                r--
            //因为nums已经排好序  所以sum < 0 需要移动左指针 让他变大
            }else if(sum < 0){
                l++
            //因为nums已经排好序  所以sum > 0 需要移动右指针 让他变小
            }else if(sum > 0){
                r--
            }
        }
    }
    return result
};