以下go程序应该生成一个整数片的所有排列:
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) {
*res = append(*res, s)
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)
}
输出是意外的
[[1 2 4 3] [1 2 4 3] [1 3 4 2] [1 3 4 2] [1 4 2 3] [1 4 2 3] [2 1 4 3] [2 1 4 3] [2 3 4 1] [2 3 4 1] [2 4 1 3] [2 4 1 3] [3 2 4 1] [3 2 4 1] [3 1 4 2] [3 1 4 2] [3 4 2 1] [3 4 2 1] [4 2 1 3] [4 2 1 3] [4 3 1 2] [4 3 1 2] [4 1 2 3] [4 1 2 3]]
我不明白这里有什么问题。我将不胜感激任何帮助。 谢谢!
答案 0 :(得分:2)
您正在传递指向同一切片的指针。最后你会得到一堆指向结果中相同切片的指针,所以当然所有的值都是相同的 - 它是反复打印的相同切片。
值得注意的是,切片的指针很少是你想要的,因为切片已经包含指向底层数组的指针。
答案 1 :(得分:0)
不需要指向切片的指针,因为切片本身就是指针。 “切片是对数组的连续段的引用。”,reference。
您所看到的奇怪行为是因为您正在使用追加,当切片超出其容量时,需要创建具有增加容量的新切片并复制原始切片的所有内容(这是追加的内容)在幕后),因此新切片不再指向原始的底层数组。
我建议不要修改传入的参数,而是将切片作为函数的返回值返回。
func permute(nums []int) [][]int {
res := permuteHlp(nums, 0, new([]int))
return res
}
我建议你阅读golang.org上关于切片内部的博文,here
编辑:
我添加了一个重构器,从this answer获取算法。
package main
import (
"fmt"
)
func permutations(arr []int)[][]int{
var helper func([]int, int)
res := [][]int{}
helper = func(arr []int, n int){
if n == 1{
tmp := make([]int, len(arr))
copy(tmp, arr)
res = append(res, tmp)
} else {
for i := 0; i < n; i++{
helper(arr, n - 1)
if n % 2 == 1{
tmp := arr[i]
arr[i] = arr[n - 1]
arr[n - 1] = tmp
} else {
tmp := arr[0]
arr[0] = arr[n - 1]
arr[n - 1] = tmp
}
}
}
}
helper(arr, len(arr))
return res
}
func main() {
x := []int{1,2,3,4}
d := permutations(x)
fmt.Print(d)
}
通常你不希望有一个指向切片的指针,而是从函数返回一个新的,另一个要评论的东西,如果可能的话尽量不使用递归,因为golang没有尾调用优化,它的循环表现令人惊讶。希望它有所帮助!