【问题标题】:Golang append a number to an int array, the value of adjacent element in array changes, why?golang给一个int数组追加一个数字,数组中相邻元素的值发生变化,为什么?
【发布时间】:2022-01-26 21:12:14
【问题描述】:

我正在尝试使用 Golang 解决一些动态编程问题。我写了一个类似的函数

func main() {
    fmt.Println(HowSum(5, []int{1, 2, 5}))
}

func HowSum(targetNum int, numbers []int) []int {
  retAry = make([][]int, targetNum+1)
  retAry[0] = make([]int, 0)
  for i := 0; i <= targetNum; i++ {
    if retAry[i] != nil {
      for _, num := range numbers {
        if i+num <= targetNum {
          fmt.Print("Before:", i, " round, num =", num, retAry, "\n")
          retAry[i+num] = append(retAry[i], num)
          fmt.Print("After :", i, " round, num =", num, retAry, "\n\n")
        }
      }
    }
  }
  return retAry[targetNum]
}

部分结果如下。

...
Before:3 round, num =2 [[] [1] [1 1] [1 1 1] [1 1 1 1] [5]]
After :3 round, num =2 [[] [1] [1 1] [1 1 1] [1 1 1 2] [1 1 1 2]]
...
[1 1 1 2 1]

当程序将 retAry[5] 从 [5] 替换为 [1 1 1 2] 时,retAry[4] 中的数组从 [1 1 1 1] 更改为 [1 1 1 2]。会发生什么?

但是,如果替换 retAry[i+num] = append(retAry[i], num)retAry[i+num] = append([]int{num}, retAry[i]...) ,我可以得到正确答案。

...
Before:3 round, num =2 [[] [1] [1 1] [1 1 1] [1 1 1 1] [5]]
After :3 round, num =2 [[] [1] [1 1] [1 1 1] [1 1 1 1] [2 1 1 1]]
...
[1 1 1 1 1]

谁能帮忙解释一下我犯了什么错误?

代码是here

【问题讨论】:

  • 这个blog post 可以更清楚地说明为什么修改一个切片的底层数组会对另一个看似不相关的切片产生影响。

标签: arrays go append


【解决方案1】:

However, if replace retAry[i+num] = append(retAry[i], num) to retAry[i+num] = append([]int{num}, retAry[i]...) , I can get the correct answer.

说明:

retAry[i+num] = append(retAry[i], num) 在 retAry[i+num] 和 retAry[i] 之间共享同一个数组。如果您修改一个切片,则另一个切片也可以更改。

func main() {
    s1 := append([]int{}, 1, 2, 3) // len: 3, cap 4 []int{1, 2, 3, 0}

    // it appends 4 to 4th index and assign new slice to s2.
    // s2 is share the same array with s1
    // s1 : len: 3, cap 4 []int{1, 2, 3, 4}
    // s2 : len: 4, cap 4 []int{1, 2, 3, 4}
    s2 := append(s1, 4)

    // s3 is share the same array with s1 and s2 as well
    // when you append 4th index to s1, and assign to s3, both s1 and s2 will change as well
    // s1 : len: 3, cap 4 []int{1, 2, 3, 5}
    // s2 : len: 4, cap 4 []int{1, 2, 3, 5}
    // s3 : len: 4, cap 4 []int{1, 2, 3, 5}
    s3:= append(s1, 5)
    fmt.Println(s2, s3) // output [1 2 3 5] [1 2 3 5]
}

retAry[i+num] = append([]int{num}, retAry[i]...)

[]int{num} 你用一个新数组初始化一个新切片,然后将 retAry[i] 中的每个元素附加到新数组中。它们不再是 retAry[i+num] 和 retAry[i] 之间的任何引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-02
    • 2020-06-17
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    相关资源
    最近更新 更多