Golang append a number to an int array, the value of adjacent element in array changes, why?

huangapple go评论75阅读模式
英文:

Golang append a number to an int array, the value of adjacent element in array changes, why?

问题

我正在尝试使用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]

有人可以帮忙解释一下我犯了什么错误吗?

代码在这里

英文:

I am trying to solve some dynamic programming problems by using Golang. I wrote a function like

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 &lt;= targetNum; i++ {
 	if retAry[i] != nil {
      for _, num := range numbers {
	    if i+num &lt;= targetNum {
          fmt.Print(&quot;Before:&quot;, i, &quot; round, num =&quot;, num, retAry, &quot;\n&quot;)
		  retAry[i+num] = append(retAry[i], num)
          fmt.Print(&quot;After :&quot;, i, &quot; round, num =&quot;, num, retAry, &quot;\n\n&quot;)
		}
	  }
	}
  }
  return retAry[targetNum]
}

A part of results is as follows.

...
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]

The array in retAry[4] is changed from [1 1 1 1] to [1 1 1 2] when the program replace retAry[5] from [5] to [1 1 1 2]. What happen?

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.

...
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]

Could anyone can help to explain what mistake I made?

The code is here

答案1

得分: 0

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

解释:

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}

	// 它将 4 追加到第 4 个索引,并将新的切片赋值给 s2。
	// s2 与 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 也与 s1 和 s2 共享同一个数组
	// 当你将第 4 个索引追加到 s1,并赋值给 s3 时,s1 和 s2 也会改变
	// 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) // 输出 [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] 之间不再有任何引用关系。

英文:

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.

Explain:

retAry[i+num] = append(retAry[i], num) is sharing the same array between retAry[i+num] and retAry[i]. If you modify one slice, other slice could be changed as well.

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} you initialize a new slice with a new array, and then append every elements in retAry[i] to the new array. They aren't any reference between retAry[i+num] and retAry[i] anymore.

huangapple
  • 本文由 发表于 2021年12月28日 14:09:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/70503358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定