TopK问题:查找数组中的前K个更大或最小数。
相对简单的一般解决方案可以使用排序、本地排序和大/小根堆。大根堆用于解决全K的小问题,小根堆用于解决全K的大问题。
解决TopK问题,将数组的前K个元素编成堆,然后从K 1元素扫描到最后。对于父K大问题,请使用小根堆。扫描期间,如果元素大于堆元素,则会弹出堆元素,并插入新元素。前面的K小问题反过来使用大根堆,如果元素小于堆顶,则弹出堆顶,插入新元素。
堆有两个主要任务。Push()插入新元素,Pop()弹出堆元素,根堆弹出更大的元素,小根堆相反。Go没有内置可以直接调用的堆容器,所以需要可以使用的接口。
要引用“Container/heap”中的定义,请使用sort .您可能需要实现Interface内的方法,例如Less()、Len()、Swap()和Push()。
Type接口{
Sort。界面。
推(x接口{})//add x as element len()
Pop()接口{ }//remove and return element len()-1。
}
参考go的源代码目录中的小根堆示例/usr/local/go/src/container/heap/example _ intheap _ test . go。
堆使用的切片存储区。自定义Pop()方法返回切片结束元素,只需减少一个空格,而Push()方法只需向堆中使用的切片添加一个新元素。具体堆的建立和排序是由“container/heap”包内的其他方法完成的,根据他们是如何实现的,看看源代码就知道了。
Package heap_test
Import(
Container/heap
“Fmt”
)。
//An IntHeap is a min-heap of ints。
Type IntHeap []int
func(h intheap)len()int { return len(h)}
Func (h int heap) less (I,j int) bool {return h [I] h [j]}
Func (h int heap) swap (I,j int) {h [I],h [j]=h [j],h [I]}
Func (h * intheap) push (x接口{}) {
//push and pop use pointer receivers because they modify the slice ' s length,
//not just its contents。
*h=append(*h,x.(int))
}
Func (h * intheap) pop()接口{} {
Old :=*h
N :=len(old)
X :=old[n-1]
* h=OLD[0 3360N-1]
Return x
}
//this example inserts several ints into an int heap,checks the minimum,
//and removes them in order of priority。
Func Example_intHeap() {
H :=IntHeap{2,1,5}
Heap。Init(h)。
Heap。Push(h,3)
fmt . printf(' minimum 3360% d \ n ',(* h) [0])
For h.Len() 0 {
Fmt。Printf('%d ',heap .Pop(h))
}
//output3360
//minimum 3360 1
//1 2 3 5
}
问题练习:刀的意思是Offer 40。最小K数
这个问题要想次得到K的小数目,就要用大根堆。在上面的例子中,我们已经知道小根堆是如何实现的,那大根堆怎么办?主要区别是Less()方法。也就是说,如果存在I元素,则可以简单地定义Less()方法
如果大于元素j,则认为元素I小于元素j,执行反向排序。要想轻松地重复使用此堆,可以在堆结构中添加字段,不管是大根堆还是小根堆。在Less()方法中,根据此字段确定返回方法。扫描一次传入数组,将前K个元素初始化为大根堆,从k 1元素开始扫描,如果大于堆顶部,则取出堆顶部,插入新元素。堆顶部元素可以通过h[0]简单地获得。
import“container/heap”
Type IntHeap []int
func(h intheap)len()int { return len(h)}
//为实现大根堆,Less大于时返回小
Func (h int heap) less (I,j int) bool {return h [I] h [j]}
Func (h int heap) swap (I,j int) {h [I],h [j]=h [j],h [I]}
Func (h * intheap) push (x接口{}) {
*h=append(*h,x.(int))
}
Func (h * intheap) pop()接口{} {
Old :=*h
N :=len(old)
X :=old[n-1]
* h=OLD[0 3360N-1]
Return x
}
//根堆
Func getleastnumbers (arr [] int,k int) [] int {
H :=make(IntHeap,k)
Hp:=h
复制(H,Intheap(ARR[3360K 1]))
Heap。Init(惠普)
FOR I :=K;艾琳(ARR);I {
If arr[i]h[0]{
Heap。Pop(惠普)
Heap。Push(hp,arr[i])
}
}
Return h
}