如何编写一个返回set中最小值的函数?我不只是在寻找一个解决方案(我知道我可以在迭代第一个元素时初始化最小值,然后设置一个我初始化最小值的布尔变量),而不是惯用解决方案。由于go没有原生集,假设我们有map[Cell]bool
。
答案 0 :(得分:2)
地图是在Go中实现集合的惯用方法。惯用代码使用bool或struct {}作为地图的值类型。后者使用较少的存储空间,但需要在键盘上输入更多内容才能使用。
假设单元格的最大值为maxCell
,则此函数将计算min:
func min(m map[Cell]bool) Cell {
min := maxCell
for k := range m {
if k < min {
min = k
}
}
return min
}
如果Cell是数字类型,则可以将maxCell设置为math constants之一。
使用地图的任何解决方案都需要在键上循环。
除地图外,您还可以保留heap以找到最低要求。这将需要更多的存储和代码,但可以更高效,具体取决于集合的大小以及调用最小函数的频率。
答案 1 :(得分:2)
一种不同的方法,取决于您的设置有多大,使用自我排序切片可以更有效:
type Cell uint64
type CellSet struct {
cells []Cell
}
func (cs *CellSet) Len() int {
return len(cs.cells)
}
func (cs *CellSet) Swap(i, j int) {
cs.cells[i], cs.cells[j] = cs.cells[j], cs.cells[i]
}
func (cs *CellSet) Less(i, j int) bool {
return cs.cells[i] < cs.cells[j]
}
func (cs *CellSet) Add(c Cell) {
for _, v := range cs.cells {
if v == c {
return
}
}
cs.cells = append(cs.cells, c)
sort.Sort(cs)
}
func (cs *CellSet) Min() Cell {
if cs.Len() > 0 {
return cs.cells[0]
}
return 0
}
func (cs *CellSet) Max() Cell {
if l := cs.Len(); l > 0 {
return cs.cells[l-1]
}
return ^Cell(0)
}
playground //这是一个测试文件,将其复制到set_test.go并运行go test -bench=. -benchmem -v
BenchmarkSlice 20 75385089 ns/op 104 B/op 0 allocs/op
BenchmarkMap 20 77541424 ns/op 158 B/op 0 allocs/op
BenchmarkSliceAndMin 20 77155563 ns/op 104 B/op 0 allocs/op
BenchmarkMapAndMin 1 1827782378 ns/op 2976 B/op 8 allocs/op