问题起因
写一道回溯算法题,把ans二维数组作为函数参数传入,想在函数里面,不停地append,最后返回ans
实际发现ans打印出来是空的,就很奇怪,因为我是事先分配好空间的,理论上不会发生扩容,底层数组是共用的,咋回事
func permute(nums []int) [][]int {ans := make([][]int, 0, len(nums)*len(nums))item := append([]int{}, nums...)backtracking(0, item, nums,&ans)return ans
}func backtracking(i int, cur, nums []int, ans [][]int) {if i == len(nums) {tmp := slices.Clone(cur)ans = append(ans, tmp)return}for j:=i;j<len(nums);j++ {swap(i, j, cur)backtracking(i+1, cur, nums, ans)swap(i, j, cur)}
}func swap(i,j int, nums []int) {nums[i], nums[j] = nums[j], nums[i]
}
传递指针问题解决
*ans [][]int
分析原因
切片里不止有底层数组啊,还有Len Cap这些基础数据类型;修改是不可见的
在Go语言中,切片(slice)作为函数参数传递时,是通过值传递的,但这里传递的值是切片头(slice header),其中包含指向底层数组的指针、长度和容量。这意味着函数内部可以通过这个指针修改底层数组的元素,但如果对切片进行追加(append)操作,可能会改变切片头的值(例如长度和指针),这些更改不会反映到外部切片中,因为函数内部操作的是切片头的副本。
import "slices"func permute(nums []int) [][]int {ans := make([][]int, 0)n := len(nums)// 创建当前排列的副本,用于回溯操作cur := make([]int, n)copy(cur, nums)// 定义闭包函数var backtrack func(int)backtrack = func(i int) {if i == n {// 将当前排列添加到答案中tmp := slices.Clone(cur)ans = append(ans, tmp)return}for j := i; j < n; j++ {// 交换元素cur[i], cur[j] = cur[j], cur[i]backtrack(i + 1)// 回溯,恢复交换cur[i], cur[j] = cur[j], cur[i]}}backtrack(0)return ans
}
参考,最下面评论区