数组 - 三数求和

215 阅读1分钟

描述

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

输入:nums = [-1, 0, 1, 2, -1, -4]

输出:[ [-1, 0, 1], [-1, -1, 2] ]

解题思路一

根据两数求和的思路,可以将求和问题转为求差,那么可以固定一个参数,剩下的就转化为两数求和问题了

先把固定的元素给排出出来,将剩下的数组转化为二维数组的问题

求解

// 先准备两数求和
function twoSums(sums, target) {
    let obj = {}
    
    for(let i = 0; i < sums.length; i++) {
        const r = target - sums[i]
        if(obj[r] !== undefined) {
            return [obj[r], sums[i]]
        } else {
            obj[sums[i]] = sums[i]
        }
    }
    
    return []
}

function threeSums(nums){
    let res = []

    for (let i =0; i < nums.length; i++) {
        const copyNums = [...nums] // 浅拷贝一份
        const curNum = (copyNums || []).splice(i, 1)[0] // 拿到当前的元素
        const otherTwo = twoSums(copyNums, -curNum)
        if(otherTwo && otherTwo.length > 0) {
               res.push([].concat(curNum, ...otherTwo))
        }
    }
    
    return res
    
}

运行结果

image.png

很明显不符合要求,很多重复的结果,那么是否可以有优化的策略呢

解题思路二,双指针法

对于使用双指针,需要数组有序,因此先排序

function threeSums(nums) {
    nums.sort()
    const length = nums.length
    const res = []
    
    for(let i = 0; i < length - 2; i++) {
        let j = i + 1
        let k = length - 1
        
        // 如果遇到连续元素则跳过
        if (i > 0 && nums[i] === nums[i-1]) {
            continue
        }
        
        while(j < k) {
            if(nums[i] + nums[j] + nums[k] === 0) {
                res.push([nums[i], nums[j], nums[k]])
                j++
                k--
                while(j < k && nums[j] === nums[j-1]) {
                    j++
                }
                
                while(j < k && nums[k] === nums[k+1]) {
                    k--
                }
            } else if (nums[i] + nums[j] + nums[k] < 0) {
                j++
                
               while(j < k && nums[j] === nums[j-1]) {
                    j++
                }
            } else if (nums[i] + nums[j] + nums[k] > 0) {
                k--
                
               while(j < k && nums[k] === nums[k+1]) {
                    k--
                }
            }
        }
    }
    
    return res
}

参考别人答案,死记硬背的。。。