〇 slice 扩容规则

slice扩容规则.png
slice扩容规则2.png

〇 slice append 修改值

在解答 LeetCode 78. Subsets 时,我的原答案是

  1. func subsets(nums []int) [][]int {
  2. res := make([][]int, 0)
  3. track := make([]int, 0)
  4. backtrack(track, nums, &res, 0)
  5. return res
  6. }
  7. // track 路径
  8. // nums 选择列表
  9. // 结束条件:start == len(nums)
  10. func backtrack(track, nums []int, res *[][]int, start int) {
  11. *res = append(*res, track)
  12. for i := start; i < len(nums); i++ {
  13. track = append(track, nums[i])
  14. backtrack(track, nums, res, i+1)
  15. track = track[:len(track)-1]
  16. }
  17. }

但得出的结果却是 [[] [3] [1 3] [1 2 3] [1 3] [3] [2 3] [3]]
可见某个切片的原数组的值被改动了,经过分析可知是 track 切片
由于程序运行的具体情况很复杂,在此不做分析

如果想要将一个切片的数据追加到另一个切片中,建议使用 copy 和中间变量,而非 append

  1. package main
  2. import "fmt"
  3. func main() {
  4. s1 := [][]int{{1}, {2}, {3}}
  5. s2 := []int{4}
  6. s1 = append(s1, s2)
  7. fmt.Println(s1) // [[1] [2] [3] [4]]
  8. s2[0] *= 10
  9. fmt.Println(s1) // [[1] [2] [3] [40]]
  10. }
  1. package main
  2. import "fmt"
  3. func main() {
  4. s1 := [][]int{{1}, {2}, {3}}
  5. s2 := []int{4}
  6. temp := make([]int, len(s2))
  7. copy(temp, s2)
  8. s1 = append(s1, temp)
  9. fmt.Println(s1) // [[1] [2] [3] [4]]
  10. s2[0] *= 10
  11. fmt.Println(s1) // [[1] [2] [3] [4]]
  12. }

将原答案改为

  1. func subsets(nums []int) [][]int {
  2. res := make([][]int, 0)
  3. track := make([]int, 0)
  4. backtrack(track, nums, &res, 0)
  5. return res
  6. }
  7. // track 路径
  8. // nums 选择列表
  9. // 结束条件:start == len(nums)
  10. func backtrack(track, nums []int, res *[][]int, start int) {
  11. temp := make([]int, len(track))
  12. copy(temp, track)
  13. *res = append(*res, temp)
  14. for i := start; i < len(nums); i++ {
  15. track = append(track, nums[i])
  16. backtrack(track, nums, res, i+1)
  17. track = track[:len(track)-1]
  18. }
  19. }

通过题目