亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用指針追加到片 [][]int 時出錯

使用指針追加到片 [][]int 時出錯

Go
小唯快跑啊 2022-09-26 15:43:47
當我試圖從LC解決一個問題“子集II”時,我遇到了一個奇怪的問題。該代碼從給定的功率集生成一個功率集。但是,當我運行代碼時,它失敗了,因為其中一個集合不正確。集合 [0,3,5,7] 被替換為 [0,3,5,9](因此被追加兩次)。在將集合附加到 res 之前,我有一個 print 語句(在代碼中突出顯示),它打印正確的功率集。我能想到的唯一問題是使用指針將值附加到切片中,但是由于它不會同時運行,我不明白為什么會出現爭用條件。如果有人能指出我的錯誤,請表示贊賞。package mainimport (    "fmt"    "sort")func ValueCount( nums []int) map[int]int{  hm := make(map[int]int)  for _,v := range(nums){    if c, ok := hm[v]; ok {      hm[v] = c + 1    }else{      hm[v] = 1    }  }  return hm}func subsetsWithDup(nums []int) [][]int {    var res [][]int    res = append(res,[]int{})    sort.Ints(nums)  hashMap := ValueCount(nums)  var t []int  printTest(nums, t, &res, hashMap)    return res}func printTest(nums []int, t []int, res *[][]int, hm map[int]int) {  if len(nums) == 0 {    return  }  for i:= 0; i < len(nums); {    v := nums[i]    x := nums[i:]    for  k:= 0; k< hm[v]; k++ {      var a,b []int      for z:= 0; z<k+1; z++ {         a = append(t,x[z])      }      fmt.Println(a) // <--------- Prints the values that gets appended to res      *res = append(*res, a)          b = a      printTest(nums[i+hm[v]:], b, res, hm)    }    i += hm[v]  }  }func main(){    n := []int{9,0,3,5,7}    fmt.Println("Find the power set of:", n)    fmt.Println(subsetsWithDup(n))}// [0,3,5,7] changes to // [0,3,5,9] in the output
查看完整描述

2 回答

?
猛跑小豬

TA貢獻1858條經驗 獲得超8個贊

該錯誤發生在第 40 行:


a = append(t, x[z])

快速修復方法是更改此循環:for


        for k := 0; k < hm[v]; k++ {

            var a, b []int

            for z := 0; z < k+1; z++ {

                a = append(t, x[z])

            }

            fmt.Println(a) // <--------- Prints the values that gets appended to res

            *res = append(*res, a)

            b = a

            printTest(nums[i+hm[v]:], b, res, hm)

        }

對此:


        for k := 0; k < hm[v]; k++ {

            var a, b []int

            a = make([]int, len(t))

            copy(a, t)

            for z := 0; z < k+1; z++ {

                a = append(a, x[z])

            }

            fmt.Println(a) // <--------- Prints the values that gets appended to res

            *res = append(*res, a)

            b = a

            printTest(nums[i+hm[v]:], b, res, hm)

        }

這與Go如何使用切片作為數據結構有關。當內置函數的第一個參數是切片參數時,它會復制一些對程序員來說不直觀的切片內部數據。然后,它修改了參數切片 和新創建的切片 。appendta


如果您有興趣了解更多信息,我建議您閱讀切片內部。


完整程序已編輯:


package main


import (

    "fmt"

    "sort"

)


func ValueCount(nums []int) map[int]int {

    hm := make(map[int]int)

    for _, v := range nums {

        if c, ok := hm[v]; ok {

            hm[v] = c + 1

        } else {

            hm[v] = 1

        }

    }

    return hm

}


func subsetsWithDup(nums []int) [][]int {

    var res [][]int

    res = append(res, []int{})

    sort.Ints(nums)

    hashMap := ValueCount(nums)

    var t []int

    printTest(nums, t, &res, hashMap)

    return res

}


func printTest(nums []int, t []int, res *[][]int, hm map[int]int) {

    if len(nums) == 0 {

        return

    }

    for i := 0; i < len(nums); {

        v := nums[i]

        x := nums[i:]

        for k := 0; k < hm[v]; k++ {

            var a, b []int

            a = make([]int, len(t))

            copy(a, t)

            for z := 0; z < k+1; z++ {

                a = append(a, x[z])

            }

            fmt.Println(a) // <--------- Prints the values that gets appended to res

            *res = append(*res, a)

            b = a

            printTest(nums[i+hm[v]:], b, res, hm)

        }

        i += hm[v]

    }


}


func main() {

    n := []int{9, 0, 3, 5, 7}

    fmt.Println("Find the power set of:", n)

    fmt.Println(subsetsWithDup(n))

}

新輸出:


Find the power set of: [9 0 3 5 7]

[0]

[0 3]

[0 3 5]

[0 3 5 7]

[0 3 5 7 9]

[0 3 5 9]

[0 3 7]

[0 3 7 9]

[0 3 9]

[0 5]

[0 5 7]

[0 5 7 9]

[0 5 9]

[0 7]

[0 7 9]

[0 9]

[3]

[3 5]

[3 5 7]

[3 5 7 9]

[3 5 9]

[3 7]

[3 7 9]

[3 9]

[5]

[5 7]

[5 7 9]

[5 9]

[7]

[7 9]

[9]

[[] [0] [0 3] [0 3 5] [0 3 5 7] [0 3 5 7 9] [0 3 5 9] [0 3 7] [0 3 7 9] [0 3 9] [0 5] [0 5 7] [0 5 7 9] [0 5 9] [0 7] [0 7 9] [0 9] [3] [3 5] [3 5 7] [3 5 7 9] [3 5 9] [3 7] [3 7 9] [3 9] [5] [5 7] [5 7 9] [5 9] [7] [7 9] [9]]



查看完整回答
反對 回復 2022-09-26
?
aluckdog

TA貢獻1847條經驗 獲得超7個贊

使用(和重用)切片結果時要非常小心 - 特別是在以后更改這些切片值時。由于切片具有后備數組,因此引用的數據可能會以非常意外的方式更改!


問題的快速解決方法是將切片結果復制到新切片。這可確保對原始切片的更改不會引入 bug(尤其是在遞歸算法中)。


復制切片:


func copyIntSlice(a []int) []int {

    c := make([]int, len(a))

    copy(c, a) // `a` can now grow/shrink/change without affecting `c`

    return c

}

然后只需從您的主代碼中調用它:


aCopy := copyIntSlice(a)

*res = append(*res, aCopy)


printTest(nums[i+hm[v]:], aCopy, res, hm)

https://play.golang.org/p/1p8Z4sV9foQ


查看完整回答
反對 回復 2022-09-26
  • 2 回答
  • 0 關注
  • 123 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號