三数之和
给你一个包含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 = []
输出:[]
思路
- 本题主要是对三元组进行去重,如果是map,key不可为切片,因此map方法不能使用。
- 针对本题,首先将数组排序,然后在遍历数组的过程中去除重复解。
- 在遍历数组的时候:用i确定开始遍历的位置(也是target的位置),如果当前元素和前面的元素相等,则跳出本次循环,去除重复解。
- 继续使用左右指针在区间[i+1,len(nums)-1]寻找使得nums[left]+nums[right]+target==0的解。
- 如果nums[left]+nums[right]+target==0,如果在寻找的过程中left和right与下一位置重复,则去除重复解,并同时将left,right移到下一位置,寻找新的解。
- 如果nums[left]+nums[right]+target<0,则left右移
- 如果nums[left]+nums[right]+target>0,则right左移
解法
func threeSum(nums []int) [][]int {
sort.Ints(nums)
res:=[][]int{}
for i:=0;i<len(nums);i++{ // 在遍历数组的时候:用i确定开始遍历的位置(也是target的位置)
left:=i+1
right:=len(nums)-1
if i>0&&nums[i]==nums[i-1] // 如果当前元素和前面的元素相等,则跳出本次循环,去除重复解
continue
}
if nums[i]>0{ // 排序后i对应的位置为最小,其后面的均大于它
break
}
target:=nums[i] // 将target初始化为索引为i的元素
for left<right{ // 对区间[left,right]进行左右指针查找
if nums[left]+nums[right]+target>0{ // 如果nums[left]+nums[right]+target>0,则right左移
right--
}else if nums[left]+nums[right]+target<0{ // 如果nums[left]+nums[right]+target<0,则left右移
left++
}else{ // 如果nums[left]+nums[right]+target==0
res=append(res,[]int{target,nums[left],nums[right]})
left++
right--
for left<right&&nums[left]==nums[left-1]{ // 如果left与下一位置重复,则将left移到下一位
left++
}
for left<right&&nums[right]==nums[right+1]{ // 如果right与下一位置重复,则将right移到下一位
right--
}
}
}
}
return res
}