Home >Backend Development >Golang >append() may modify the original slice (2d slice recursively)

append() may modify the original slice (2d slice recursively)

WBOY
WBOYforward
2024-02-06 08:27:04469browse

append() 可能会修改原始切片(2d 切片递归)

Problem content

(The encoding problem is to generate solutions for all combinations whose sum reaches the target, the number of times each element in candidate arr is not Restricted.)

2D[][]int Slice theList Passed by reference in recursion appending []int (tmpCombo) , but after appending, one of the elements is modified, [3 3 3 3 3 3] is changed to [3 3 3 3 3 2]. So I have to copy tmpCombo before executing append(). append(arr, ele) Did the original arr slice change? If so, I should observe more of the original arr being modified, but this only happens once. So I'm actually confused about how this slice append() works.

https://go.dev/play/p/PH10SxiF7A5

<code>
...
theList: [.... [3 3 3 3 3 3]]
theList: [.... [3 3 3 3 3 2] [3 3 3 3 2 2 2]]
</code>

(I also tried doing a for loop and continuing to append to the slice, the original slice didn't change at all...)

package main

import (
    "fmt"
    "sort"
)

func combinationSum(candidates []int, target int) [][]int {
    sort.Sort(sort.Reverse(sort.IntSlice(candidates)))

    var theList [][]int
    var tmpCombo []int
    rCombo(candidates, target, 0, tmpCombo, &theList)

    return theList
}

func rCombo(candidates []int, target int, index int, tmpCombo []int, theList *[][]int) {
    if index >= len(candidates) {
        fmt.Println("index:", index)
        return
    }
    // fmt.Println(target)
    if candidates[index] > target {
        rCombo(candidates, target, index+1, tmpCombo, theList)
        return
    }

    for i:=index; i<len(candidates); i++ {
        if candidates[i] < target {
                rCombo(candidates, target-candidates[i], i, append(tmpCombo, candidates[i]), theList)
        } else if candidates[i] == target {

            // NOTE: simply append tmpCombo will give weird output [3 3 3 3 3 3] changed to [3 3 3 3 3 2].              
            *theList = append(*theList,  append(tmpCombo, target))

            // cpyCombo := make([]int, len(tmpCombo))
            // copy(cpyCombo, tmpCombo)
            // *theList = append(*theList,  append(cpyCombo, target))

            // appended slice didn't change address so tmpCombo was modified
            for i:=0; i<len(*theList); i++ {
                fmt.Printf("%d %p ", (*theList)[i], (*theList)[i])
            }
            fmt.Println()

            // fmt.Println("cc", tmpCombo, candidates[i], append(cpyCombo, candidates[i]), theList )
        }
    }
}

func main() {
    // 2,3,5
    candidates := []int{7,3,2}
    target := 18
    combinationSum(candidates, target)

 // test: this does not change the original s...
// var s []int = make([]int, 6)
// // var x []int

// for i:=0; i<200; i++ {
//  x := append(s, i)
//  fmt.Println(x, s)
// }
}

Correct answer


Since this answer illustrates the same problem, I understand nowhttps://www.php.cn/link/0d924f0e6b3fd0d91074c22727a53966一个>.

Basically, if a slice stores the data in one location with the specified capacity, but has the length as a separate property... in my case, doing multiple append(tmpCombo, target) The data in tmpCombo is actually modified because the variable isn't reallocated/updated with the new length, and the underlying data at the same location is modified (when not reallocated).

tldr. Make sure to pass a new copy of the same data using one of the following methods:

make()Create a new slice and copy()End (make()Allocate specific capacity)

or

append(nil []int, arr...]. (append() may allocate more memory, but is suitable for frequent modifications)

The above is the detailed content of append() may modify the original slice (2d slice recursively). For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete