#数据结构与算法学习笔记#剑指Offer61:数据流中的中位数 + 最大堆 + 最小堆(Java、C/C++)

版权声明:本文为博主NJU_ChopinXBP原创文章,发表于CSDN,仅供交流学习使用,转载请私信或评论联系,未经博主允许不得转载。感谢您的评论与点赞。 https://blog.csdn.net/qq_20304723/article/details/88073762

2019.3.2     《剑指Offer》从零单刷个人笔记整理(66题全)目录传送门​​​​​​​

这道题有技巧,想要实时获得中位数,需要最大堆+最小堆的数据结构,将所有大于等于中位数的元素放在最小堆,将所有小于中位数的元素放在最大堆。

对数据总数进行计数,要保证:

1. 在总数为奇数时,直接弹出最小堆堆顶即为中位数,即此时最小堆元素比最大堆元素多1个。

2.在总数为偶数时,弹出最小堆堆顶和最大堆堆顶取平均即为中位数,即此时最大堆元素和最小堆元素相等。

因此,对于每次数据流中的新元素:

1.若该元素是第奇数个元素,元素先经过最大堆过滤,将最大堆堆顶元素(最小值)放入最小堆。

2.若该元素是第偶数个元素,元素先经过最小堆过滤,将最小堆堆顶元素(最大值)放入最大堆。


题目描述

如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。


Java实现:

/**
 * 
 * @author ChopinXBP
 * 如何得到一个数据流中的中位数?
 * 如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
 * 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
 * 我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
 * 
 */

import java.util.Comparator;
import java.util.PriorityQueue;

public class GetMedianofStream_62 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	private PriorityQueue <Integer> minheap = new PriorityQueue <>();
	private PriorityQueue<Integer> maxheap = new PriorityQueue<>(15, new Comparator<Integer>() {
		@Override
		//反转为最大堆
		public int compare(Integer o1, Integer o2) {
			return o2.compareTo(o1);
		}
	});
	private int count = 0;
	
	//所有大于等于中位数的数据放在最小堆,所有小于中位数的数据放在最大堆
    public void Insert(Integer num) {
    	count++;
    	//当数据总数为奇数时,数据先进入最大堆筛选,最大堆顶部元素进入最小堆
    	if((count & 0x01) == 1) {
    		maxheap.add(num);
    		minheap.add(maxheap.poll());
    	}
    	//当数据总数为偶数时,数据先进入最小堆筛选,最小堆顶部元素进入最大堆
    	else {
    		minheap.add(num);
    		maxheap.add(minheap.poll());
    	}
    }

    public Double GetMedian() {
    	//数据为偶数时,最小堆和最大堆顶部为中位数
    	if((count & 0x01) == 0) {
    		return new Double((minheap.peek() + maxheap.peek())) / 2;
    	}
    	//数据为奇数时,最小堆顶部为中位数
    	else {
    		return new Double(minheap.peek());
    	}
    }
}

C++实现示例:

class Solution {
    priority_queue<int, vector<int>, less<int> > p;
    priority_queue<int, vector<int>, greater<int> > q;
     
public:
    void Insert(int num){
        if(p.empty() || num <= p.top()) p.push(num);
        else q.push(num);
        if(p.size() == q.size() + 2) q.push(p.top()), p.pop();
        if(p.size() + 1 == q.size()) p.push(q.top()), q.pop();
    }
    double GetMedian(){ 
      return p.size() == q.size() ? (p.top() + q.top()) / 2.0 : p.top();
    }
};

#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/88073762