【问题标题】:Golang: Passing in Slice as Reference issueGolang:传入切片作为参考问题
【发布时间】:2014-10-09 19:16:04
【问题描述】:

我正在尝试编写一个计算数组中反转的程序,但由于引用问题,我的数组没有正确排序,因此即使我认为切片是通过 Golang 中的引用传递的,我的计数也会混乱。

这是我的代码:

package main

import (
    "fmt"
)

func InversionCount(a []int) int {
    if len(a) <= 1 {
        return 0
    }
    mid := len(a) / 2
    left := a[:mid]
    right := a[mid:]
    leftCount := InversionCount(left) //not being sorted properly due to reference issues 
    rightCount := InversionCount(right) //not being sorted properly due to reference issues

    res := make([]int, 0, len(right)+len(left)) //temp slice to hold the sorted left side and right side

    iCount := mergeCount(left, right, &res)

    a = res        //assigns the original slice with the temp slice values
    fmt.Println(a) //a in the end is not sorted properly for most cases 
    return iCount + leftCount + rightCount
}

    func mergeCount(left, right []int, res *[]int) int {
        count := 0

        for len(left) > 0 || len(right) > 0 {
            if len(left) == 0 {
                *res = append(*res, right...)
                break
            }
            if len(right) == 0 {
                *res = append(*res, left...)
                break
            }
        if left[0] <= right[0] {
            *res = append(*res, left[0])
            left = left[1:]
        } else { //Inversion has been found
            count += len(left)
            *res = append(*res, right[0])
            right = right[1:]
        }
    }

    return count
}

func main() {
    test := []int{4,2,3,1,5}
    fmt.Print(InversionCount(test))
}

解决此问题的最佳方法是什么?我试图通过强制mergeCount函数接受数组的引用来做类似于我对res数组所做的事情,但它看起来很混乱,它会给我带来错误。

【问题讨论】:

    标签: pointers go slice


    【解决方案1】:

    您要么必须将指针传递给切片,例如:

    func InversionCount(a *[]int) int {
        if len(*a) <= 1 {
            return 0
        }
        mid := len(*a) / 2
        left := (*a)[:mid]
        right := (*a)[mid:]
        leftCount := InversionCount(&left)   //not being sorted properly due to reference issues
        rightCount := InversionCount(&right) //not being sorted properly due to reference issues
    
        res := make([]int, 0, len(right)+len(left)) //temp slice to hold the sorted left side and right side
    
        iCount := mergeCount(left, right, &res)
    
        *a = res
        fmt.Println(a) //a in the end is not sorted properly for most cases
        return iCount + leftCount + rightCount
    }
    

    playground

    或使用copy 并将a = res 更改为copy(a, res)

    playground

    【讨论】:

    • @DavidTrinh 记得投票并标记对您有帮助的答案。
    【解决方案2】:

    与其对切片进行变异,不如让函数返回在合并步骤中获得的切片。

    这是这种形式的代码,包括一些类似单元测试的代码,它将有效版本与天真的 O(N^2) 计数进行比较。

    package main
    
    import "fmt"
    
    // Inversions returns the input sorted, and the number of inversions found.
    func Inversions(a []int) ([]int, int) {
        if len(a) <= 1 {
            return a, 0
        }
        left, lc := Inversions(a[:len(a)/2])
        right, rc := Inversions(a[len(a)/2:])
        merge, mc := mergeCount(left, right)
        return merge, lc + rc + mc
    }
    
    func mergeCount(left, right []int) ([]int, int) {
        res := make([]int, 0, len(left)+len(right))
        n := 0
        for len(left) > 0 && len(right) > 0 {
            if left[0] >= right[0] {
                res = append(res, left[0])
                left = left[1:]
            } else {
                res = append(res, right[0])
                right = right[1:]
                n += len(left)
            }
        }
        return append(append(res, left...), right...), n
    }
    
    func dumbInversions(a []int) int {
        n := 0
        for i := range a {
            for j := i + 1; j < len(a); j++ {
                if a[i] < a[j] {
                    n++
                }
            }
        }
        return n
    }
    
    func main() {
        cases := [][]int{
            {},
            {1},
            {1, 2, 3, 4, 5},
            {2, 1, 3, 4, 5},
            {5, 4, 3, 2, 1},
            {2, 2, 1, 1, 3, 3, 4, 4, 1, 1},
        }
        for _, c := range cases {
            want := dumbInversions(c)
            _, got := Inversions(c)
            if want != got {
                fmt.Printf("Inversions(%v)=%d, want %d\n", c, got, want)
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-07-14
      • 2016-10-27
      • 1970-01-01
      • 2021-12-20
      • 2021-09-15
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 2018-08-31
      相关资源
      最近更新 更多