四數之和
給定一個包含 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
}