附加字符串和数组的类似Go函数的行为不符合预期

时间:2015-11-21 20:30:41

标签: algorithm go

我有两个Go功能:

func permutation(prefix, str []int) {
    n := len(str)
    if n == 0 {
        fmt.Println(prefix)
    } else {
        for i := 0; i < n; i++ {
            permutation(
                append(prefix, str[i]),
                append(str[0:i], str[i+1:]...),
            )
        }
    }
}

func perms(prefix, str string) {
    n := len(str)
    if n == 0 {
        fmt.Println(prefix)
    } else {
        for i := 0; i < n; i++ {
            perms(
                prefix+string(str[i]),
                string(str[0:i])+string(str[i+1:]),
            )
        }
    }
}

第一个采用一个int数组,第二个采用一个字符串。然后它们都计算数组的所有排列或字符串。

我可以像这样运行它们:

permutation([]int{}, []int{1, 2, 3})
perms("", "123")

他们的输出不一样:

$ go run main.go
[1 2 3]
[1 3 3]
[3 3 3]
[3 3 3]
[3 3 3]
[3 3 3]
123
132
213
231
312
321

我想添加我缺少的数组会有一些细微差别。我似乎无法弄明白。知道发生了什么事吗?

1 个答案:

答案 0 :(得分:2)

虽然str1+str2确实返回新的(在内存方面无关)​​字符串,但append不会以这种方式运行。例如,append(str[0:i], str[i+1:]...)将销毁str的原始内容,并使用str[i:]覆盖str[i+1:]。这是因为str[0:i]将有能力在不分配新缓冲区的情况下附加str[i+1:]

解决方案是在每次迭代中创建一个全新的数组。至少strappend(prefix, str[i])对此问题免疫。例如:

for i := 0; i < n; i++ {
    var s []int
    s = append(s, str[0:i]...)
    s = append(s, str[i+1:]...)
    permutation(append(prefix, str[i]), s)
}

https://play.golang.org/p/lXwu39AA0V

有关切片和追加机制的更多信息:

http://blog.golang.org/go-slices-usage-and-internals

https://blog.golang.org/slices