Maison  >  Article  >  développement back-end  >  append() peut modifier la tranche d'origine (tranche 2D récursive)

append() peut modifier la tranche d'origine (tranche 2D récursive)

WBOY
WBOYavant
2024-02-06 08:27:04444parcourir

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

Contenu du problème

(Le problème d'encodage est de générer des solutions pour toutes les combinaisons dont la somme atteint la cible, avec un nombre illimité de fois pour chaque élément de l'arr. candidat.)

Comment fonctionne

2D [][]int 切片 theList 在附加 []int (tmpCombo) 的递归中通过引用传递,但附加后,其中一个元素被修改,[3 3 3 3 3 3] 更改为 [3 3 3 3 3 2]。所以我必须在执行 append() 之前复制 tmpComboappend(arr, ele) 是否更改了原始 arr 切片?如果是这样,我应该观察到更多原始的 arr 被修改,但这种情况只发生一次。所以我实际上很困惑这个切片 append().

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>

(J'ai aussi essayé de faire une boucle for et de continuer à ajouter à la tranche, la tranche d'origine n'a pas changé du tout...)

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)
// }
}

Réponse correcte


Puisque cette réponse illustre le même problème, je comprends maintenanthttps://www.php.cn/link/0d924f0e6b3fd0d91074c22727a53966一个>.

Fondamentalement, si une tranche stocke les données dans un emplacement avec la capacité spécifiée, mais a la longueur comme propriété distincte... dans mon cas, faire plusieurs append(tmpCombo, target) 实际上会修改 tmpCombo des données qu'elle contient, puisque la variable n'est pas réaffectée/Le la nouvelle longueur est mise à jour et les données sous-jacentes au même emplacement sont modifiées (lorsqu'elles ne sont pas réaffectées).

tldr. Assurez-vous de transmettre une nouvelle copie des mêmes données en utilisant l'une des méthodes suivantes :

make()新建切片并copy()结束(make()Allouer une capacité spécifique)

ou

append(nil []int, arr...]. (append() Peut allouer plus de mémoire, mais convient aux modifications fréquentes)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer