• 剑指 Offer 41. 数据流中的中位数 && Leetcode 259


    地址 https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/
    地址 https://leetcode-cn.com/problems/find-median-from-data-stream/
    另同 Poj3784(对顶堆维护中位数)

    如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。
    如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
    
    例如,
    [2,3,4] 的中位数是 3
    [2,3] 的中位数是 (2 + 3) / 2 = 2.5
    
    设计一个支持以下两种操作的数据结构:
    void addNum(int num) - 从数据流中添加一个整数到数据结构中。
    double findMedian() - 返回目前所有元素的中位数。
    
    示例 1:
    输入:
    ["MedianFinder","addNum","addNum","findMedian","addNum","findMedian"]
    [[],[1],[2],[],[3],[]]
    输出:[null,null,null,1.50000,null,2.00000]
    
    示例 2:
    输入:
    ["MedianFinder","addNum","findMedian","addNum","findMedian"]
    [[],[2],[],[3],[]]
    输出:[null,null,2.00000,null,2.50000]
     
    
    限制:
    最多会对 addNum、findMedian 进行 50000 次调用。
    

    原始做法是每次输入就就进行一次排序,然后输出答案。
    但是更好的方案是使用对顶堆,减少排序设计的范围,从而提升速度

    class MedianFinder {
    public:
    	/** initialize your data structure here. */
    
    	priority_queue<int, vector<int>, greater<int> > q_small;  // 小顶堆  
    	priority_queue<int, vector<int>, less<int> > q_big;     // 大顶堆,默认  
    	MedianFinder() {
    
    	}
    
    	void addNum(int num) {
    		//如果两堆均为0 则push小堆
    
    		//如果两堆均不为0 查看比小堆的大 还是比大堆的小 优先小堆
    
    		if (q_small.empty() && q_big.empty()) { 
    			q_small.push(num); }
    		else if (!q_small.empty() && num >= q_small.top()) { 
    			q_small.push(num); }
    		else if (!q_big.empty() && num <= q_big.top()) { 
    			q_big.push(num); }
    		else if (!q_small.empty()) { q_small.push(num); }
    		else if (!q_big.empty()) { q_big.push(num); }
    
    		//调整两对大小
    		while (!q_small.empty() && !q_big.empty() && q_small.top() < q_big.top()) {
    			int val = q_small.top(); q_small.pop();
    			q_big.push(val);
    		}
    
    		//调整两堆数量
    		while (q_small.size() > (q_big.size() + 1) ) {
    			int val = q_small.top(); q_small.pop();
    			q_big.push(val);
    		}
    
    		while (q_small.size() < q_big.size()) {
    			int val = q_big.top(); q_big.pop();
    			q_small.push(val);
    		}
    
    	}
    
    	double findMedian() {
    		if ((q_small.size() + q_big.size()) % 2 == 0) {
    			return 1.0*(q_small.top()+q_big.top()) / 2.0;
    		}
    		else {
    			return q_small.top();
    		}
    
    		return 0.0;
    	}
    };
    
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/itdef/p/14693458.html
Copyright © 2020-2023  润新知