数据流的中位数(优先队列)

中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。

  • 例如 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 以内的答案将被接受。

 

思路:使用两个优先队列,分别存放中位数左边的数和中位数右边的数,故需要他们分别按降序和升序排序,并且在添加元素时要注意两个队列的大小之差最多为1,这样就能直接从队头得到中位数。

class MedianFinder {
public:
/**queMin、queMax存储 int 类型的数据,并使用 vector<int> 作为内部容器。
 *less<int> 与greater<int>是一个比较函数对象,分别实现了降序和升序排序逻辑
 */
    priority_queue<int, vector<int>, less<int>> queMin;//降序
    priority_queue<int, vector<int>, greater<int>> queMax;//升序
    MedianFinder() {
        
    }
    
    void addNum(int num) {
        if(queMin.empty()||num<=queMin.top()){
            queMin.push(num);
            //规定queMin最多只能存放比queMax的大小多1,这样当数组元素个数为奇数时,中位数就在queMin中
            if(queMin.size()>queMax.size()+1){
                queMax.push(queMin.top());
                queMin.pop();
            }
        }else{
            queMax.push(num);
            //根据规定,queMax的大小不能超过queMin的大小
            if(queMax.size()>queMin.size()){
                queMin.push(queMax.top());
                queMax.pop();
            }
        }
    }
    
    double findMedian() {
        if((queMax.size()+queMin.size())%2!=0){//根据规定,当数组元素个数为奇数时,中位数就在queMin中
            return queMin.top();
        }else{
            return (queMin.top()+queMax.top())/2.0;
        }
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

 

posted on 2025-01-04 15:38  _月生  阅读(41)  评论(0)    收藏  举报