三数之和(js解决)

原题:牛客三数之和

题目大意

给出一个有n个元素的数组S,S中是否有元素a,b,c满足a+b+c=0?找出数组S中所有满足条件的三元组。

分析

在这里插入图片描述

1.首先将该数组进行快速排序,得到一个非降序数组,利于后续从左到右查找。
2.遍历该数组使用Map得到每个数出现的次数。
3.遍历该数组,假设当前遍历的值为一个解答的最小数,即为图中的i位置,现在问题转换为是否存在两个位于i之后的数,使得它们之和为0,。
4.设left为i+1,假定left为可能解的较小值,则可得arr[left]需小于-arr[i]/2,所以可在该范围内遍历left。若存在某个值= -(arr[i]+arr[left]) ,则满足要求,将它push入解集中。

关键点

1.当遍历到i位置时,应当在map中对该key对应的值-1,以免干扰结果。
2.当遍历到i位置时,若arr[i]==arr[i-1],则continue。
3.当arr[left]=arr[i]+arr[left]时,即arr[left]=arr[i]/2。需要判断arr[left]在数组i位置后出现的次数,若>=2,则满足条件。

js代码

//快速排序
function quickSort( arr ) {
    if(arr.length <= 1) return arr;
    const tar = arr[0];
    let left = [],right = [];
    for(let i = 1;i< arr.length;i++) {
        if(arr[i] <= tar) left.push(arr[i]);
        else right.push(arr[i]);
    }
    return quickSort(left).concat([tar],quickSort(right));
}
function threeSum( num ) {
    if(num.length<3) return [];
    let arr = quickSort(num);
    let mp = new Map();
    let res = [];
    arr.forEach(function(value,index,arr) {
        if(mp.has(value)) mp.set(value,mp.get(value)+1);
        else mp.set(value,1);
    })
    for(let i =0;i<arr.length;i++) {
        if(arr[i]>0) break;
        if(i>0&&arr[i]==arr[i-1]) continue;
        mp.set(arr[i],mp.get(arr[i])-1);
        let left = i+1,maxn = Math.floor(-arr[i]/2);
        while(arr[left]<=maxn) {
            if(left>i+1&&arr[left]==arr[left-1]) {
                left++;
                continue;
            }
            else if(arr[left] == -(arr[i]+arr[left]) && mp.get(arr[left])>=2) {
                res.push([arr[i],arr[left],arr[left]]);
            }
            else if(mp.has(-(arr[i]+arr[left])) &&arr[left] != -(arr[i]+arr[left])) {
                res.push([arr[i],arr[left],-(arr[i]+arr[left])]);
            }
            left++;
        }
    }
    return res;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值