为什么切片值会发生变化?

时间:2017-03-03 06:57:36

标签: go

附加到二维切片的切片的值稍后会更改。为什么会发生?

完整代码如下:

import "sort"
import "fmt"

func combinationSum(candidates []int, target int) [][]int {
    sort.Ints(candidates)
    var ret [][]int
    var curlist []int
    combinationSumRecursive(candidates, target, 0, curlist, &ret)
    fmt.Println("ret", ret)
    return ret
}

func combinationSumRecursive(candidates []int, target int, curCandidateIdx int, curlist []int, ret *[][]int) {
    if target == 0 {
        fmt.Println("put", curlist)
        *ret = append(*ret, curlist)
        return
    }
    for i:=curCandidateIdx;i<len(candidates);i++{
        if candidates[i] > target {
            break
        }
        combinationSumRecursive(candidates, target - candidates[i], i, append(curlist, candidates[i]), ret)
    }
}

INPUT是:

[7,3,2]
18

OUTPUT如下:

put [2 2 2 2 2 2 2 2 2]
put [2 2 2 2 2 2 3 3]
put [2 2 2 2 3 7]
put [2 2 2 3 3 3 3]
put [2 2 7 7]
put [2 3 3 3 7]
put [3 3 3 3 3 3]
ret [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 7 3 3] [2 2 2 2 3 7] [2 2 2 3 3 3 3] [2 2 7 7] [2 3 3 3 7] [3 3 3 3 3 3]]

ret中的第二个切片已更改。预计会[2 2 2 2 2 2 3 3]

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

这是由第curlist行追加中切片combinationSumRecursive(candidates, target - candidates[i], i, append(curlist, candidates[i]), ret)的更改引起的。

解决方法是在将curlist传递给下一个递归级别之前将其重新分配给附加结果。

package main

import "sort"
import "fmt"

func combinationSum(candidates []int, target int) [][]int {
    sort.Ints(candidates)
    var ret [][]int
    var curlist []int
    combinationSumRecursive(candidates, target, 0, curlist, &ret)
    fmt.Println("ret", ret)
    return ret
}

func combinationSumRecursive(candidates []int, target int, curCandidateIdx int, curlist []int, ret *[][]int) {
    if target == 0 {
        fmt.Println("put", curlist)
        *ret = append(*ret, curlist)
        return
    }
    for i := curCandidateIdx; i < len(candidates); i++ {
        if candidates[i] > target {
            break
        }
        curlist = append(curlist, candidates[i])
        combinationSumRecursive(candidates, target-candidates[i], i, curlist, ret)
    }
}

func main() {
    combinationSum([]int{7, 3, 2}, 18)
}

这会产生:

put [2 2 2 2 2 2 2 2 2]
put [2 2 2 2 2 2 3 3]
put [2 2 2 2 3 7]
put [2 2 2 3 3 3 3]
put [2 2 7 7]
put [2 3 3 3 7]
put [3 3 3 3 3 3]
ret [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3] [2 2 2 2 3 7] [2 2 2 3 3 3 3] [2 2 7 7] [2 3 3 3 7] [3 3 3 3 3 3]]

[编辑]首先阅读this。这解释了虽然你看到切片头的地址发生了变化,但在追加后,支持数组仍然是相同的。

然后this就是您案例中发生的事情的一个例子。 在你的情况下,问题很难看出,因为递归调用和当前索引重新定位到curlist

答案 1 :(得分:1)

您仅在curlist时打印target==0但由于递归功能中的append(curlist, candidates[i])而不断变化。 如果您尝试其他候选人,例如:[5,3,2],您会注意到其他切片不仅会改变第二个切片。

尝试在curlist

时复制target=0
if target == 0 {
    fmt.Println("put", curlist)
    newCurlist := make([]int, len(curlist))
    copy(newCurlist, curlist)
    *ret = append(*ret, newCurlist)
    return
}

这应该有用!