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

}