四数之和
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。
注意:答案中不可以包含重复的四元组。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:
输入:nums = [], target = 0
输出:[]
提示:
0 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/4sum
解题思路
做过之前的三数之和,感觉这一道题就是在三数之和上面添加一层循环就可以了----先排序,最后两层双指针。但是提交的时候遇到一些问题了。
错误代码一
func fourSum(nums []int, target int) [][]int {
if len(nums) < 4 {
return nil
}
sort.Ints(nums)
result := make([][]int,0)
for i:=0;i<len(nums);i++{
// 第一层循环
tmp := threeSum(nums[i],nums[i+1:],target-nums[i])
result = append(result,tmp...)
}
return result
}
func threeSum(val int,nums []int,target int) [][]int {
result := make([][]int,0)
for i:=0;i<len(nums);i++{
x,y := i+1,len(nums)-1
tmp := target - nums[i]
for x < y {
// 这里直接是为了去重
for x <= len(nums)-2 && nums[x] == nums[x+1]{
x++
continue
}
for y > x && nums[y] == nums[y-1] {
y--
continue
}
if nums[x] + nums[y] == tmp {
arr := []int{val,nums[i],nums[x],nums[y]}
result = append(result,arr)
x++
y--
}else if nums[x] + nums[y] > tmp {
y--
}else if nums[x] + nums[y] < tmp {
x++
}
}
}
return result
}
用例:nums := []int{2,2,2,2,2},target=8的时候出现错误,结果为:[[2 2 2 2] [2 2 2 2] [2 2 2 2]]。因为在第一层循环没有去重的情况下,即使后面上层去重了,也会导致出现重复的情况。于是想着给第一层添加当i>0的时候,如果此时的数等于上一个数则直接跳出本次循环。
错误代码二
func fourSum(nums []int, target int) [][]int {
if len(nums) < 4 {
return nil
}
sort.Ints(nums)
result := make([][]int,0)
for i:=0;i<len(nums);i++{
if i>0 && nums[i] == nums[i-1] {
continue
}
tmp := threeSum(nums[i],nums[i+1:],target-nums[i])
result = append(result,tmp...)
}
return result
}
func threeSum(val int,nums []int,target int) [][]int {
result := make([][]int,0)
for i:=0;i<len(nums);i++{
x,y := i+1,len(nums)-1
tmp := target - nums[i]
for x < y {
// 这里直接是为了去重
for x <= len(nums)-2 && nums[x] == nums[x+1]{
x++
continue
}
for y > x && nums[y] == nums[y-1] {
y--
continue
}
if nums[x] + nums[y] == tmp {
arr := []int{val,nums[i],nums[x],nums[y]}
result = append(result,arr)
x++
y--
}else if nums[x] + nums[y] > tmp {
y--
}else if nums[x] + nums[y] < tmp {
x++
}
}
}
return result
}
给第一层去重了之后,提交运行,还是同一个例子出现错误,结果为:[[2 2 2 2] [2 2 2 2]]。因为第一层已经去重了,出现问题只能是之后了。经过调试发现,在第二层这里,没有对本次遍历的值是否与上一次的相等进行判断。给第二层添加当i>0的时候,如果此时的数等于上一个数则直接跳出本次循环。,
错误代码三
func fourSum(nums []int, target int) [][]int {
if len(nums) < 4 {
return nil
}
sort.Ints(nums)
result := make([][]int,0)
for i:=0;i<len(nums);i++{
if i>0 && nums[i] == nums[i-1] {
continue
}
tmp := threeSum(nums[i],nums[i+1:],target-nums[i])
result = append(result,tmp...)
}
return result
}
func threeSum(val int,nums []int,target int) [][]int {
result := make([][]int,0)
for i:=0;i<len(nums);i++{
if i>0 && nums[i] == nums[i-1] {
continue
}
x,y := i+1,len(nums)-1
tmp := target - nums[i]
for x < y {
// 这里直接是为了去重
for x <= len(nums)-2 && nums[x] == nums[x+1]{
x++
continue
}
for y > x && nums[y] == nums[y-1] {
y--
continue
}
if nums[x] + nums[y] == tmp {
arr := []int{val,nums[i],nums[x],nums[y]}
result = append(result,arr)
x++
y--
}else if nums[x] + nums[y] > tmp {
y--
}else if nums[x] + nums[y] < tmp {
x++
}
}
}
return result
}
这次上面的例子通过,但是当nums=[]int{-2,-1,-1,1,1,2,2},target=0的时候,结果只为:[[-2 -1 1 2]]。与正确结果不符合,还有一个[-1,-1,1,1]。经过调试发现是因为第三层的判断出现了错误,因为y > x && nums[y] == nums[y-1],会导致x=y的情况而导致在判断-1,-1,1,1这个结果的时候直接跳出循环。因为是y-1会导致判断向前看,但是我们每一次的判断是向后看的,也就是我们需要看nums[y]不与nums[y+1]相等。
正确代码
上面的修改完之后,就正确咯
func fourSum(nums []int, target int) [][]int {
if len(nums) < 4 {
return nil
}
sort.Ints(nums)
log.Println(nums)
result := make([][]int,0)
for i:=0;i<len(nums);i++{
if i>0 && nums[i] == nums[i-1] {
continue
}
tmp := threeSum(nums[i],nums[i+1:],target-nums[i])
result = append(result,tmp...)
}
return result
}
func threeSum(val int,nums []int,target int) [][]int {
result := make([][]int,0)
for i:=0;i<len(nums);i++{
if i>0 && nums[i] == nums[i-1] {
continue
}
x,y := i+1,len(nums)-1
tmp := target - nums[i]
for x < y {
// 这里的循环,都是为了让下一次的循环值等于上次的循环值
if x>i+1 && nums[x] == nums[x-1] {
x++
continue
}
if y>=0 && y<len(nums)-1 && nums[y] == nums[y+1] {
y--
continue
}
if nums[x] + nums[y] == tmp {
arr := []int{val,nums[i],nums[x],nums[y]}
result = append(result,arr)
x++
y--
}else if nums[x] + nums[y] > tmp {
y--
}else if nums[x] + nums[y] < tmp {
x++
}
}
}
return result
}