这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
前言
在看到这道算法题的题目时,我第一感觉就是简单,不就三个数相加,应该和之前做过的两数之和差不多,通过map轻松拿下,但事实并不是这样的,这个题和之前的两数之和半毛钱关系都没有。。。
题目描述
给你一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c ,使得 a+b+c=0?请你找出所有和为0且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
解题思路
- 首先从题目入手,答案中不能包含重复的三元组,那么我们判断的范围直接判断到小于nums.length-2即可,也就是当输入数组长度小于3的时候直接输出[]
- 这道题刚拿到手的时候是无从下手的,可以先通过sort排序来把输入数组进行排序,这样看起来思路就清晰了,我们可以从前那个数也就是i,再拿个数i+1,当做start,从尾部拿个数,当做end,这三个数相加和0比较,如果等于0则存入我们的结果数组,如果小于0,则start++,如果大于0,则end--,知道start<end不成立为止
- 但有一次成立并存入结果之后,我们这时要同时进行start++,end--
- 还有一个重要的点,当进行start++和end--的时候一定要和前一个值进行判断,如果不判断就会存在重复的三元数组了
- 这道题非常重要的两点就是,首先排序(这是思想),然后就是时刻去重,首先再每次循环的时候要对nums[i]和nums[i-1]进行比较,相同就跳过,这时去重,其次是start++和end--的时候再次去重,这样得到的结果就是没有重复的三元组了
- 直接来代码,如下
/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function(nums) {
const result =[]
nums.sort(function(a,b){
return a-b
})
for(let i=0;i<nums.length -2;i++){
if(nums[i] !==nums[i-1]){ //这里是第一次去重
let start = i+1
let end = nums.length-1
while(start<end){
if(nums[i]+nums[start]+nums[end]===0){
result.push([nums[i],nums[start],nums[end]])
start++
end--
while(start<end && nums[start]===nums[start-1]){ //这里是第二次去重
start++
}
while( start<end &&nums[end]===nums[end+1]){ //这里是第二次去重
end--
}
}else if(nums[i]+nums[start]+nums[end]<0){
start++
}else{
end--
}
}
}
}
return result
};
总结
本题主要思想就是通过排序从大到小排列,然后通过双重去重来得到结果,这题还是很有巧劲的,如果用暴力必会超时,LeetCode运行结果如下:
如果xdjmm有更好的见解,欢迎分享出来。