【问题标题】:Subset check with slices in Go在 Go 中使用切片进行子集检查
【发布时间】:2013-09-23 14:51:04
【问题描述】:

我正在寻找一种有效的方法来检查一个切片是否是另一个切片的子集。我可以简单地遍历它们来检查,但我觉得必须有更好的方法。

例如

{1, 2, 3} 是 {1, 2, 3, 4} 的子集
{1, 2, 2} 不是 {1, 2, 3, 4} 的子集

有效地做到这一点的最佳方法是什么?

谢谢!

【问题讨论】:

  • 你想要任何类型的值吗?
  • 切片是否排序?
  • 先排序,然后迭代较小的切片,在较大的切片中进行二分查找。

标签: arrays go subset slice


【解决方案1】:

如果您的切片已排序,那么就可以了。

package main

import "fmt"

// Subset return whether a is a sublist of b. Both a and b must be (weakly) ascending.
func Subset(a, b []int) bool {
    for len(a) > 0 {
        switch {
        case len(b) == 0:
            return false
        case a[0] == b[0]:
            a = a[1:]
            b = b[1:]
        case a[0] < b[0]:
            return false
        case a[0] > b[0]:
            b = b[1:]
        }
    }
    return true
}

func main() {
    cases := []struct {
        a, b []int
        want bool
    }{
        {[]int{1, 2, 3}, []int{1, 2, 3, 4}, true},
        {[]int{1, 2, 2}, []int{1, 2, 3, 4}, false},
    }
    for _, c := range cases {
        if Subset(c.a, c.b) != c.want {
            fmt.Printf("Subset(%v, %v) = %v, want %v\n", c.a, c.b, Subset(c.a, c.b), c.want)
        }
    }
}

【讨论】:

    【解决方案2】:

    我认为解决子集问题最常见的方法是通过地图。

    package main
    
    import "fmt"
    
    // subset returns true if the first array is completely
    // contained in the second array. There must be at least
    // the same number of duplicate values in second as there
    // are in first.
    func subset(first, second []int) bool {
        set := make(map[int]int)
        for _, value := range second {
            set[value] += 1
        }
    
        for _, value := range first {
            if count, found := set[value]; !found {
                return false
            } else if count < 1 {
                return false
            } else {
                set[value] = count - 1
            }
        }
    
        return true
    }
    
    func main() {
        fmt.Println(subset([]int{1, 2, 3}, []int{1, 2, 3, 4}))
        fmt.Println(subset([]int{1, 2, 2}, []int{1, 2, 3, 4}))
    }
    

    检查重复值的能力相对不常见。上面的代码解决了所要求的问题(参见:http://play.golang.org/p/4_7Oh-fgDQ)。如果您打算使用重复值,则必须像上面的代码一样保留计数。如果不会有重复值,您可以通过使用布尔值而不是整数来更紧凑地解决问题。

    【讨论】:

      猜你喜欢
      • 2021-12-24
      • 2019-01-02
      • 2019-12-22
      • 1970-01-01
      • 2013-03-20
      • 2016-12-01
      • 1970-01-01
      • 2020-03-01
      • 2016-02-24
      相关资源
      最近更新 更多