LeetCode—295. 数据流的中位数(困难)

295. 数据流的中位数(困难)

题目描述: 中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。 例如, [2,3,4] 的中位数是 3 [2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构: void addNum(int num) - 从数据流中添加一个整数到数据结构中。 double findMedian() - 返回目前所有元素的中位数。

考察重点:利用sort.IntSlice完成数组的排序并实现小顶堆,继承IntSlice完成数组的逆序并实现大顶堆; 大小顶堆配合查询中位数;声明大顶堆存放较小的一半元素,堆顶存放上半区最大元素;小顶堆存放较大的一半元素,堆顶存放下半区最小元素;中位数即是二者均值或大顶堆堆顶元素。 go实现大小顶堆

package DataStructure

import (
	"sort"
)

//真小顶堆
type MinHeap struct {
          
   
	sort.IntSlice
}

func NewMinHeap() *MinHeap {
          
   
	return &MinHeap{
          
   IntSlice: sort.IntSlice{
          
   }}
}

func (h *MinHeap) Push(a interface{
          
   }) {
          
   
	h.IntSlice = append(h.IntSlice, a.(int))
}

func (h *MinHeap) Pop() interface{
          
   } {
          
   
	a := h.IntSlice
	v := a[len(a)-1]
	h.IntSlice = a[:len(a)-1]
	return v
}

type ReverseIntSlice []int

func (x ReverseIntSlice) Len() int           {
          
    return len(x) }
func (x ReverseIntSlice) Less(i, j int) bool {
          
    return x[i] > x[j] }
func (x ReverseIntSlice) Swap(i, j int)      {
          
    x[i], x[j] = x[j], x[i] }

type MaxHeap struct {
          
   
	ReverseIntSlice
}

func NewMaxHeap() *MaxHeap {
          
   
	return &MaxHeap{
          
   ReverseIntSlice: ReverseIntSlice{
          
   }}
}

func (h *MaxHeap) Push(a interface{
          
   }) {
          
   
	h.ReverseIntSlice = append(h.ReverseIntSlice, a.(int))
}

func (h *MaxHeap) Pop() interface{
          
   } {
          
   
	a := h.ReverseIntSlice
	v := a[len(a)-1]
	h.ReverseIntSlice = a[:len(a)-1]
	return v
}

//这只是一个用sort方法仿制的堆,耗时仍然等于对一个数组进行排序
type Heap struct {
          
   
	HeapItem sort.IntSlice
}

func NewHeap() (h *Heap) {
          
   
	return &Heap{
          
   HeapItem: sort.IntSlice{
          
   }}
}

func (h *Heap) Push(a int) {
          
   
	h.HeapItem = append(h.HeapItem, a)
	sort.Sort(h.HeapItem)
}

func (h *Heap) Pop() int {
          
   
	temp := h.HeapItem[0]
	h.HeapItem = h.HeapItem[1:]
	return temp
}

实现中位数查找

package leetcodeProject

import (
	"container/heap"
	d "DataStructure"
)

type MedianFinder struct {
          
   
	MaxItem *d.MaxHeap		//声明一个大顶堆,一个小顶堆   大顶堆用来存放前一半比较小的数,小顶堆用来存放后一半比较大的数,即小顶堆堆顶大于大顶堆堆顶
	MinItem *d.MinHeap
}

func Constructor6() MedianFinder {
          
   
	return MedianFinder{
          
   MaxItem: d.NewMaxHeap(), MinItem: d.NewMinHeap()}
}

/**
	先将新元素加入大顶堆,再将大顶堆堆顶元素(最大值)加入小顶堆
	始终保证大顶堆元素==小顶堆元素||小顶堆元素+1
	否则,将小顶堆堆顶(最小值)加入大顶堆

	比如 3,4,1,2
	3 3加入大堆 3加入小堆 “小堆多于大堆” 3加入大堆    小:   大:3
	4 4加入大堆 4加入小堆 “小堆等于大堆” 		     小:4  大:3
	1 1加入大堆 3加入小堆 “小堆多于大堆” 3加入大堆	  小:4  大:1 3
	2 2加入大堆 3加入小堆 “小堆等于大堆” 			 小:4 3 大:1  2
*/
func (h *MedianFinder) AddNum(num int) {
          
   
	heap.Push(h.MaxItem, num)
	heap.Push(h.MinItem, heap.Pop(h.MaxItem).(int))
	if h.MaxItem.Len() < h.MinItem.Len() {
          
   
		heap.Push(h.MaxItem, heap.Pop(h.MinItem).(int))
	}
}

func (h *MedianFinder) FindMedian() float64 {
          
   
	if h.MaxItem.Len() == h.MinItem.Len() {
          
   
		return float64(h.MaxItem.ReverseIntSlice[0]+h.MinItem.IntSlice[0]) / 2
	}
	return float64(h.MaxItem.ReverseIntSlice[0])
}
经验分享 程序员 微信小程序 职场和发展