go 二维切片append时的问题(深拷贝相关/go实现回溯法问题)
我在leetcode做的时候,用go去实现了一个回溯算法
216数组的和
func combinationSum3(k int, n int) [][]int {
res := make([][]int, 0)
path := make([]int, 0)
var backtracting func(int, int, int, int)
backtracting = func(n, k, start, target int) {
if target < 0 || len(path) > k {
return
}
if target == 0 && len(path) == k {
//注意此处
res = append(res, path)
//
return
}
for i := start; i <= 9; i++ {
path = append(path, i)
backtracting(n, k, i+1, target-i)
path = path[:len(path)-1]
}
}
backtracting(n, k, 1, n)
return res
}
当输入为3,7
输出应该为 [[1,2,4]]
但实际输出为 [[9,9,9]]
这个代码是从c++改过来的,逻辑一摸一样,怎么会呢?
后来通过debug大法找到了答案
到第一次扫描到正确答案后执行了
res = append(res, path)
看似一切正常,但是进行到下一次递归的时候,path的内容改变了,同时res的内容也被改变了
这说明append函数直接将path浅拷贝到res中去了
两者现在共享底层,导致我们在操作path的时候,改变了本应该被固定的res
那么解决方法其实也就明确了,对path做一个深拷贝,然后append
go的深拷贝方法可以通过copy函数
a:=[]int{1,2,4}
//copy的拷贝是以小的长度,所以不能指定0,否则copy没有效果
b:=make([]int,len(a))
copy(b,a)
算法正确实现
func combinationSum3(k int, n int) [][]int {
res := make([][]int, 0)
path := make([]int, 0)
var backtracting func(int, int, int, int)
backtracting = func(n, k, start, target int) {
if target < 0 || len(path) > k {
return
}
if target == 0 && len(path) == k {
//深拷贝
t:=make([]int,len(path))
res = append(res, t)
return
}
for i := start; i <= 9; i++ {
path = append(path, i)
backtracting(n, k, i+1, target-i)
path = path[:len(path)-1]
}
}
backtracting(n, k, 1, n)
return res
}
本文来自博客园,作者:北方Cc,转载请注明原文链接:https://www.cnblogs.com/beifangcc/p/16678063.html