-1

I'm attempting to solve the Subsets problem on LeetCode using Go. I've come up with the following solution:

func subsets(nums []int) [][]int {
    sol := make([][]int,0)
    temp:= make([]int,0)

    var backtrack func(idx int)
    backtrack = func(idx int) {
        sol = append(sol, temp)
        fmt.Println(temp, append([]int{},temp...))

        if idx == len(nums) {
            return
        }

        for i:= idx; i<len(nums);i++{
            temp = append(temp,nums[i])
            backtrack(i+1)
            temp = temp[:len(temp)-1]
        }

    }
    backtrack(0)
    return sol

}

However, this solution is incorrect. I have noticed that I need to use append(sol, append([]int{}, temp...)) instead of just sol = append(sol, temp).

Even though the fmt.Println(temp, append([]int{}, temp...)) statement produces the same output for both temp and append([]int{}, temp...), the corrected version using append([]int{}, temp...) actually works. Can someone explain the difference between temp and append([]int{}, temp...) in this context? Why does the corrected version work while the initial version does not?

Expected temp and append([]int{},temp...) to be the same

yisic80
  • 11
  • 2
  • 2
    It's slice aliasing. – Paul Hankin Aug 26 '23 at 13:14
  • It's undefined (decision happens at runtime based on current length and amount of allocated space, and how that compares to the number of items to be added) whether `append` does a mutation purely in-place or returns an updated item. You can't depend on it being one or the other, so you need to _always_ assume it could be both. – Charles Duffy Aug 26 '23 at 13:32
  • 2
    Does this answer your question? [Why does append modify passed slice](https://stackoverflow.com/questions/35920534/why-does-append-modify-passed-slice) -- it's also duplicative of [Why does append modify the provided slice? (See example)](https://stackoverflow.com/questions/17395261/why-does-append-modify-the-provided-slice-see-example) – Charles Duffy Aug 26 '23 at 13:33

1 Answers1

1

The problem with sol = append(sol, temp) is that you're adding the slice temp into sol, not the items "inside" the slice. A slice, as described on Slice internals blog article, is "just" a pointer to an array, a length and a capacity.

Therefore, in your case, since temp is reused in each iteration, the content of the array under temp slice is overridden, and the values inside the slice you've previously added to sol are also modified (since the array under the slice is modified). This is why you're getting the wrong result at the end, even if your fmt.Println statement shows that before appending, temp has the correct value.

As append([]int{}, temp...) creates a new slice, there is no chance the values are mutated inside that new slice, since it's not reused.

norbjd
  • 10,166
  • 4
  • 45
  • 80