我正在處理一個編程問題給定兩個整數(shù) n 和 k,返回 1 ... n 中 k 個數(shù)字的所有可能組合。輸入 n = 5,k = 4,輸出應(yīng)為 [[1,2,3,4],[1,2,3,5],[1,2,4,5],[1,3 ,4,5],[2,3,4,5]],下面是我的golang方案func combine(n int, k int) [][]int { result := [][]int{} comb := []int{} subcom(0, k, n, &comb, &result) return result}func subcom(s, k, n int, comb *[]int, result *[][]int) { if k > 0 { for i := s + 1; i <= n-k+1; i++ { c := append(*comb, i) subcom(i, k-1, n, &c, result) } } else { *result = append(*result, *comb) }}我認(rèn)為我的解決方案是正確的,但它返回 [[1 2 3 5] [1 2 3 5] [1 2 4 5] [1 3 4 5] [2 3 4 5]]。調(diào)試后發(fā)現(xiàn)result slice一開始添加了[1 2 3 4],后來改成了[1 2 3 5],導(dǎo)致重復(fù)了兩個[1 2 3 5]。但我不知道這里出了什么問題。
1 回答

Qyouu
TA貢獻1786條經(jīng)驗 獲得超11個贊
這是使用append
.
當(dāng)您的代碼運行時c:=append(*comb,i)
,它會嘗試首先使用底層數(shù)組中分配的內(nèi)存來添加一個新項,并且僅在失敗時才創(chuàng)建一個新切片。這就是改變的原因[1 2 3 4]
——[1 2 3 5]
因為它們共享相同的底層內(nèi)存。
要解決此問題,請在要附加到結(jié)果時復(fù)制:
now := make([]int,len(*comb)) copy(now,*comb) *result = append(*result,now)
或者使用復(fù)制的快捷方式:
*result = append(*result, append([]int{},*comb...))
更新:
要理解我所說的底層內(nèi)存的意思,應(yīng)該理解 Go 切片的內(nèi)部模型。
在 Go 中,一個 slice 有一個數(shù)據(jù)結(jié)構(gòu),可以SliceHeader
通過reflect
package 訪問它,它是你使用和獲取地址時所引用的unsafe.Sizeof
。
照顧SliceHeader
三個要素:Len
和Cap
a Ptr
。前兩個是微不足道的:它們是什么len()
,cap()
是為了什么。最后一個是uintptr
指向切片包含的數(shù)據(jù)的內(nèi)存。
當(dāng)您淺拷貝一個切片時,SliceHeader
會創(chuàng)建一個新的但內(nèi)容相同的切片,包括Ptr
. 所以底層內(nèi)存不是復(fù)制的,而是共享的。
- 1 回答
- 0 關(guān)注
- 173 瀏覽
添加回答
舉報
0/150
提交
取消