这里有点奇怪的。我的问题是,人们是否像我一样运行我的代码得到相同的结果?如果你这样做,这是我的代码的错(我通常是python程序员),还是golang中的错误?
系统信息:转到版本(1.1.2)linux x64(fedora 19)
关于代码的背景信息:我正在做的是找到从三角形顶部到底部的最高成本路线,这是来自project_euler 18和67
错误:我设置了一个名为pathA的变量,这是一个整数列表,加上一个新的int,用于从三角形中找到的新值 例如3,7,2追加8应该等于3,2,7,8 而且,确实如此! ......直到我设置pathB。 pathB设置正确但突然pathA与pathB的值相同。
tl; dr 当我设置另一个
时,一个变量被覆盖我的代码如下:
package main
import (
"fmt"
)
func extendPaths(triangle, prePaths [][]int) [][]int {
nextLine := triangle[len(prePaths)]
fmt.Println("#####PrePaths: ", prePaths)
fmt.Println("#####nextLine: ", nextLine)
postPaths := [][]int{{}}
for i := 0; i < len(prePaths); i++ {
route := prePaths[i]
nextA := nextLine[i]
nextB := nextLine[i+1]
fmt.Println("Next A:", nextA, "Next B:", nextB, "\n")
pathA := append(route, nextA)
fmt.Println("pathA check#1:", pathA)
pathB := append(route, nextB)
fmt.Println("pathA check#2:", pathA, "\n")
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
postPaths = postPaths[1:]
prePaths = [][]int{postPaths[0]}
for i := 1; i < len(postPaths)-1; i += 2 {
if getSum(postPaths[i]) > getSum(postPaths[i+1]) {
prePaths = append(prePaths, postPaths[i])
} else {
prePaths = append(prePaths, postPaths[i+1])
}
}
prePaths = append(prePaths, postPaths[len(postPaths)-1])
return prePaths
}
func getSum(sumList []int) int {
total := 0
for i := 0; i < len(sumList); i++ {
total += sumList[i]
}
return total
}
func getPaths(triangle [][]int) {
prePaths := [][]int{{triangle[0][0]}}
for i := 0; i < len(triangle)-1; i++ {
prePaths = extendPaths(triangle, prePaths)
}
}
func main() {
triangle := [][]int{{3}, {7, 4}, {2, 4, 6}, {8, 5, 9, 3}}
getPaths(triangle)
}
这给出了我的终端输出如下所示:
#####PrePaths: [[3]]
#####nextLine: [7 4]
Next A: 7 Next B: 4
pathA check#1: [3 7]
pathA check#2: [3 7]
#####PrePaths: [[3 7] [3 4]]
#####nextLine: [2 4 6]
Next A: 2 Next B: 4
pathA check#1: [3 7 2]
pathA check#2: [3 7 2]
Next A: 4 Next B: 6
pathA check#1: [3 4 4]
pathA check#2: [3 4 4]
#####PrePaths: [[3 7 2] [3 7 4] [3 4 6]]
#####nextLine: [8 5 9 3]
Next A: 8 Next B: 5
pathA check#1: [3 7 2 8]
pathA check#2: [3 7 2 5]
Next A: 5 Next B: 9
pathA check#1: [3 7 4 5]
pathA check#2: [3 7 4 9]
Next A: 9 Next B: 3
pathA check#1: [3 4 6 9]
pathA check#2: [3 4 6 3]
在这里你可以看到,在我设置pathA的最后4次中,它最初设置正确,但后来被pathB覆盖。
有没有人对此有任何想法?
修改
正如下面的评论所指出的,所需要的是制作新切片并从原件复制数据。这是使用http://blog.golang.org/go-slices-usage-and-internals稍微修改的代码完成的:
func AppendInt(slice []int, data ...int) []int {
m := len(slice)
n := m + len(data)
if n > cap(slice) {
newSlice := make([]int, (n+1)*2)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0:n]
copy(slice[m:n], data)
return slice
}
我还更改了另一侧的代码,我创建了切片路径A和路径B.这改为:
for i := 0; i < len(prePaths); i++ {
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := AppendInt(prePaths[i], nextA)
pathB := AppendInt(prePaths[i], nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
EDIT2:
早上很早,我在第一次编辑时犯了一个错误,我没有完全理解你的解决方案,经过一段时间的黑客攻击我最终到达那里:
此代码不起作用(pathA被覆盖):
for i := 0; i < len(prePaths); i++ {
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := append(prePaths[i], nextA)
pathB := append(prePaths[i], nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
此代码也不起作用(pathA被覆盖):
for i := 0; i < len(prePaths); i++ {
newRoute := make([]int, len(prePaths[i]), (cap(prePaths[i])+1)*2)
copy(newRoute, prePaths[i])
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := append(newRoute, nextA)
pathB := append(newRoute, nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
但是,如果我将上述2个场景混合到下面的代码中,它可以正常工作(pathA不会被覆盖):
for i := 0; i < len(prePaths); i++ {
newRoute := make([]int, len(prePaths[i]), (cap(prePaths[i])+1)*2)
copy(newRoute, prePaths[i])
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := append(newRoute, nextA)
pathB := append(prePaths[i], nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
所以,我的解决方案是制作数组的副本,并让它们都使用不同的数组。
答案 0 :(得分:5)
切片基本上是由三件事组成的结构:
运行以下代码时:
append(x, element)
它执行以下操作:
在您的代码中,您有以下内容:
pathA := append(route, nextA)
pathB := append(route, nextB)
现在有两种可能性:
len(route) == cap(route)
,将分配一个新的支持数组,pathA
和pathB
具有独立的值。len(route) < cap(route)
,因此pathA
和pathB
最终共享相同的支持数组。数组中的最后一个元素将是nextB
,因为该操作是第二次运行。似乎第一种情况适用于循环的前几次迭代,之后你会遇到第二种情况。您可以通过手动为其中一个路径制作副本来避免这种情况(使用make()
分配切片,然后使用copy()
复制旧数据)。