四数之和

给定一个包含 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
}
posted @ 2021-06-17 12:40  Myuniverse  阅读(39)  评论(0编辑  收藏  举报