Leetcode 295 Find Median from Data Stream

题目链接:https://leetcode.com/problems/find-median-from-data-stream/

解题思路

既然是是找到中位数,我们就使用两个堆,一个是大顶堆,一个小顶堆,保证两个堆满足以下条件:

  1. 大顶堆的第一个元素需要小于小顶堆的第一个元素;
  2. 大顶堆的元素数量不能小于小顶堆且最多只能多一个元素;
    满足以上条件,需要找中位数的时候,判断大顶堆是否比小顶堆元素多,如果多,直接返回大顶堆的第一个元素,否则将大,小顶堆的元素相加再除2,下面给出代码,随便使用golang重写以下堆排序。
import "fmt"

type Heap struct {
	array []int32
	f func(x int32,y int32) bool
}

func NewHeapInstance(f func(x int32,y int32) bool) *Heap{
	return &Heap{array:make([]int32,0,10),f:f}
}

func (h *Heap) Sort() {
	i := len(h.array)
	for ; i > 1; i-- {
		h.swap(i - 1,1)
		h.sink(1, i - 2)
	}
}

func (h *Heap) Create(array[]int32) {
	h.array = array
	i := len(h.array) / 2
	for ;i != 0; i-- {
		h.sink(i,len(array)-1)
	}
}

func (h *Heap) sink(index int,l int) {
	leftI := index * 2
	if leftI > l {
		return
	}
	var tmpI = 0
	rightI := index * 2 + 1

	if rightI > l {
		tmpI = leftI
	} else if h.f(h.array[leftI],h.array[rightI]) {
		tmpI = leftI
	} else {
		tmpI = rightI
	}
	if h.f(h.array[index],h.array[tmpI]) {
		return
	} else {
		h.swap(index,tmpI)
		h.sink(tmpI,l)
	}
}

func (h *Heap) sift(index int) {
	parentI := index / 2
	if parentI == 0 {
		return
	}
	if h.f(h.array[parentI],h.array[index]) {
		return
	} else {
		h.swap(parentI,index)
		h.sift(parentI)
	}
}

func (h *Heap) Put(x int32) {
	if len(h.array) == 0 {
		h.array = append(h.array,0)
	}
	h.array = append(h.array,x)
	l := len(h.array)
	h.sift(l-1)
}

func (h *Heap) Get() int32 {
	if len(h.array) > 1 {
		return h.array[1]
	} else {
		panic("heap is empty !")
	}
}

func (h *Heap) Pop() int32 {
	if len(h.array) <= 1 {
		panic("heap is empty !")
	} else {
		res := h.array[len(h.array) -1]
		h.swap(1, len(h.array) - 1)
		h.array = h.array[:len(h.array) - 1]
		h.sink(1, len(h.array)-1)
		return res
	}
}

func (h *Heap) Print() {
	for i,v := range h.array {
		fmt.Printf("index: %d, val: %d\n", i ,v)
	}
}

func (h *Heap) swap(i int, j int) {
	tmp := h.array[i]
	h.array[i] = h.array[j]
	h.array[j] = tmp
}

type MedianFinder struct {
	minHeap *Heap
	maxHeap *Heap
}


/** initialize your data structure here. */
func Constructor() MedianFinder {
	minHeap := NewHeapInstance(func(x int32, y int32) bool {
		if x < y {
			return true
		} else {
			return false
		}
	})
	maxHeap := NewHeapInstance(func(x int32, y int32) bool {
		if x < y {
			return false
		} else {
			return true
		}
	})
	return MedianFinder{minHeap:minHeap,maxHeap:maxHeap}
}


func (this *MedianFinder) AddNum(num int)  {
	if len(this.maxHeap.array) == len(this.minHeap.array) {
		this.maxHeap.Put(int32(num))
	} else {
		this.minHeap.Put(int32(num))
	}
	this.balance()
}


func (this *MedianFinder) FindMedian() float64 {
	if len(this.maxHeap.array) > len(this.minHeap.array) {
		return float64(this.maxHeap.Get())
	} else {
		return (float64(this.maxHeap.Get()) + float64(this.minHeap.Get())) / 2
	}
}

func (this *MedianFinder) balance() {
	if len(this.minHeap.array) == 0 {
		return
	}
	minT := this.minHeap.Get()
	maxT := this.maxHeap.Get()
	if maxT > minT {
		this.maxHeap.Pop()
		this.minHeap.Pop()
		this.minHeap.Put(int32(maxT))
		this.maxHeap.Put(int32(minT))
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值