LeetCode 15. 三数之和【JavaScript】

三数之和

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

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

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这个题卡了我一天,去重卡了半天,超出时间限制又卡半天。于是我决定有必要记录下来。
看看这惨痛的记录,字里行间无不透露出两个字:a~tui!小菜鸡!!
记录
我刚开始的思路是,先把数组从小到大排序,然后固定nums[i]不变,再把nums[i+1]赋值给nums[l],最后一位nums[nums.length-1]赋值给nums[r],计算三个数nums[i],nums[l]和nums[r]的和 sum 判断是否满足为 0,满足则添加进结果集,当 sum < 0 时,l++;当 sumsum >0 时,r–
当时我的代码是这样的

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
   var t=[];
    nums.sort((a, b) => a - b);
 for(let i=0;i<nums.length;i++){
     let l=i+1;
     r=nums.length-1;
     while(l<r){
     if(nums[i]+nums[l]+nums[r]==0){
       t.push([nums[i],nums[l],nums[r]]);
       l++; r--;
            }
     else if(nums[i]+nums[l]+nums[r]<0){l++;}
     else{r--;}
     }
 }
   return t;
};

然后发现我没有考虑去重,导致输出的结果是这样的:
错误示例1
于是我想到了用Set去重 ,这个时候我的代码是这样的:

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    var t=[];
    nums.sort((a, b) => a - b);
 for(let i=0;i<nums.length;i++){
     let l=i+1;
     r=nums.length-1;
     while (nums[i] === nums[++i]) {} 
     while(l<r){
     if(nums[i]+nums[l]+nums[r]==0){
       t.push([nums[i],nums[l],nums[r]]);
       l++; r--;
     }
     else if(nums[i]+nums[l]+nums[r]<0){l++;}
     else{r--;}
     }
 }
   var newArr = new Set(t);
   var arr1 = [...newArr];
   return arr1;
};

然后我发现结果没变化,我就很纳闷,后来在面向百度搜索以及对大佬提问后得知,set方法是对内存地址进行判断,而不是对象数值,好吧,果然是我菜鸡了。
然后,在参考了别人的逻辑后我把代码改成了这种:

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    var t=[];
    nums.sort((a, b) => a - b);
 for(let i=0;i<nums.length;i++){
     if (nums[i] > 0) break;
    if (i > 0 && nums[i] === nums[i - 1]) continue;//去重
     let l=i+1;
     r=nums.length-1;
     while(l<r){
     if(nums[i]+nums[l]+nums[r]==0){
       t.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--;
     }
     else if(nums[i]+nums[l]+nums[r]<0){l++;}
     else{r--;}
     }
 }
   return t;
};

于是通过了!另外附赠一个大佬的解法,此时给大佬打个广告(公众号:漫谈大前端,里面有力扣每次周赛的题解,都是用的JavaScript,对前端人士比较友好):

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums){
    var t=[];
    var i=0;
    var len=nums.length;
    nums.sort((a, b) => a - b);
    const record = new Set();
    while(i<len)
{
    if(nums[i]>0) break;
     let l=i+1;
     r=len-1;
     while(l<r){
         var sum=nums[i]+nums[l]+nums[r];
     if(sum==0){
       const key=[nums[i],nums[l],nums[r]].sort().join(',');
       if (!record.has(key)) {
           t.push([nums[i],nums[l],nums[r]]);
         record.add(key);}
         l++; r--;
     }
     else if(sum<0){l++;}
     else{r--;}
     i++;
     }
}
 return t;
};

不过这个超出时间限制了,不知道有没有人有优化这个的方法,欢迎指出!

猜你喜欢

转载自blog.csdn.net/weixin_42345596/article/details/106027146