Go语言传递切片指针生成全排列时出现异常结果求助
解决Go语言全排列生成中的重复结果问题
我一眼就看出问题所在了——你的代码踩了Go语言切片引用特性的坑!导致最终输出的全排列出现大量重复,下面来一步步分析和修复:
问题根源
- 切片引用共享底层数组:当你执行
*res = append(*res, s)时,并没有真正把当前排列的副本存入结果集,而是把切片s的引用加了进去。后续递归回溯时对s的修改(比如s = s[:len(s)-1])会直接修改已经存在于res中的切片内容,因为它们共享同一个底层数组。 - 递归中的切片复用覆盖:整个递归过程中你一直在复用同一个切片
s,回溯操作会不断修改它的长度和内容,最终导致之前保存的排列被覆盖,出现重复的结果。
修复后的代码
只需要在保存结果的时候,创建一个当前切片s的副本存入结果集即可,修改后的完整代码如下:
package main import "fmt" func permute(nums []int) [][]int { var res [][]int var s []int permuteHlp(&res, nums, 0, s) return res } func permuteHlp(res *[][]int, nums []int, i int, s []int) { if i == len(nums) { // 创建当前切片的副本,避免后续修改影响已保存的结果 temp := make([]int, len(s)) copy(temp, s) *res = append(*res, temp) return } for j := i; j < len(nums); j++ { s = append(s, nums[j]) nums[i], nums[j] = nums[j], nums[i] permuteHlp(res, nums, i+1, s) s = s[:len(s)-1] nums[i], nums[j] = nums[j], nums[i] } } func main() { x := []int{1,2,3,4} y := permute(x) fmt.Println(y) }
为什么这样修复?
当我们执行copy(temp, s)时,会把s中的元素逐一复制到新创建的切片temp中,这个temp拥有独立的底层数组,后续对s的任何修改都不会影响它。这样每一个排列都会以独立的切片形式存入结果集,就不会出现重复的情况了。
另外,你也可以用更简洁的写法替代make+copy:
*res = append(*res, append([]int(nil), s...))
这种方式通过append一个空切片并展开s的元素,同样能创建出独立的切片副本。
运行修复后的代码,就能得到[1,2,3,4]的所有24个不重复的全排列了。
内容的提问来源于stack exchange,提问作者user9823642
相关产品推荐
相关产品推荐

