双指针|三数之和
📋目录
✅ 15.三数之和
15.三数之和
⏰ 1.解题思路
- 题目要求最后的结果不能有重复的,使用哈希法要考虑最后的结果去重,很容易超时。
- 所以直接使用双指针法,具体思路是
- 先将数组进行排序,从小到大
- 最外层是一个for循环,从i下标为0 的地方开始,并且定义一个left在下标为i+1,定义下标为数组结尾为right
- 如果 nums[i] + nums[left] + nums[right] < 0 说明 此时 三数之和小了,left 就向右移动,才能让三数之和大一些,直到left与right相遇为止。
- 第一个数a = nums[i] 的去重,因为在for循环里面,所以可以直接跳过,怎么跳过呢?还要考虑一个问题是先跟下一个数比较,发现重复之后跳过还是先跳到下一个,回过头来根上一个数比较是否有重复。二者的区别就在于如过遇到下面这种数组
//通俗讲,先判断了再决定要不要跳过
if (nums[i] == nums[i+1]){
continue
}
//如果数组为[-1,-1,2],当遍历第一个数为-1,有判断下一个数为-1,那么这个数组就直接被pass掉,实际上,这个数组是符合规范
//正确写法是
if (nums[i] == nums[i-1]){
continue
}
//主要是要这个数组的和在为 0 的同时,三元组不能重复,但是里面的元素可以重复[0,0,0]
💻 2.代码
var threeSum = function(nums){
const res = [],len = nums.length
//数组排序从小到大
nums.sort((a,b)=>a-b)
for(let i = 0;i<nums.len;i++){
let iNum = num[i],l = i+1, r=len -1
//数组排过序,如果第一个大于0直接返回res
if (iNum > 0) return res;
//去重
if ( iNum == nums[i-1]) continue
while(lef<right){
let lNum = nums[l],rNum = nums[r],threeSum = iNum + lNum +rNum
//如果三数之和小于0,则左指针往右
if(threeSum < 0) l++
else if (threeSum > 0) r--
else{
res.push([iNum,lNum,rNum])
//去重
while(l < r && nums[l] == nums[l+1]) {
l++
}
while(l < r && nums[r] == nums[r-1]){
r--
}
l++
r--
}
}
}
}