中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
例如 arr = [2,3,4] 的中位数是 3 。
例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5 。
实现 MedianFinder 类:
MedianFinder() 初始化 MedianFinder 对象。
void addNum(int num) 将数据流中的整数 num 添加到数据结构中。
double findMedian() 返回到目前为止所有元素的中位数。与实际答案相差 10-5 以内的答案将被接受。
import "container/heap"
// 双堆法,大小根堆分别存储中位数的左边和右边
type MedianFinder struct {
minHeap *MinHeap
maxHeap *MaxHeap
}
type MinHeap []int
type MaxHeap []int
func (this MinHeap) Less(i, j int) bool {
return this[i] < this[j]
}
func (this MinHeap) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
}
func (this MinHeap) Len() int {
return len(this)
}
func (this *MinHeap) Push(item interface{}) {
*this = append(*this, item.(int))
}
func (this *MinHeap) Pop() interface{} {
if len(*this) == 0 {
return nil
}
old := *this
length := len(old)
item := old[length-1]
*this = old[:length-1]
return item
}
func (this MinHeap) Peek() int {
return this[0]
}
// 之所以取<,是因为后面存入大根堆时取了反,因此堆顶的值取反后便是该堆得最大值
func (this MaxHeap) Less(i, j int) bool {
return this[i] < this[j]
}
func (this MaxHeap) Swap(i, j int) {
this[i], this[j] = this[j], this[i]
}
func (this MaxHeap) Len() int {
return len(this)
}
func (this *MaxHeap) Push(item interface{}) {
*this = append(*this, item.(int))
}
func (this *MaxHeap) Pop() interface{} {
if len(*this) == 0 {
return nil
}
old := *this
length := len(old)
item := old[length-1]
*this = old[:length-1]
return item
}
func (this MaxHeap) Peek() int {
return this[0]
}
func Constructor() MedianFinder {
minHeap := &MinHeap{}
maxHeap := &MaxHeap{}
heap.Init(minHeap)
heap.Init(maxHeap)
return MedianFinder{minHeap, maxHeap}
}
func (this *MedianFinder) AddNum(num int) {
if this.minHeap.Len() == 0 || num >= this.minHeap.Peek() {
heap.Push(this.minHeap, num)
} else {
heap.Push(this.maxHeap, -num)
}
if this.minHeap.Len() > this.maxHeap.Len()+1 {
heap.Push(this.maxHeap, -heap.Pop(this.minHeap).(int))
} else if this.minHeap.Len()+1 < this.maxHeap.Len() {
heap.Push(this.minHeap, -heap.Pop(this.maxHeap).(int))
}
}
func (this *MedianFinder) FindMedian() float64 {
if this.minHeap.Len() == this.maxHeap.Len() {
return float64(this.minHeap.Peek()+(-this.maxHeap.Peek())) / 2.0
} else if this.minHeap.Len() > this.maxHeap.Len() {
return float64(this.minHeap.Peek())
}
return float64(-this.maxHeap.Peek())
}