三数之和
给你一个包含 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;
};
然后发现我没有考虑去重,导致输出的结果是这样的:
于是我想到了用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;
};
不过这个超出时间限制了,不知道有没有人有优化这个的方法,欢迎指出!