【LeetCode 295.】 Find Median from Data Stream

50 篇文章 0 订阅
4 篇文章 0 订阅

题目描述:

实现数据结构,插入数据和查找中位数。

思路:

  1. vector + sort, O ( n 2 n^2 n2)
  2. 维护一个最大堆和一个最小堆,两者元素个数最大相差1,中位数即为最小堆堆顶元素或最大堆最小堆堆顶元素平均值。用优先队列实现。 (n log(n)) 。
  3. 用二叉搜索树维护数组,两个指针指向中位数元素。用multi_set实现。时间复杂度同上。

代码:

堆:

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {}
    
    void addNum(int num) {
        if (L_.empty() || num < L_.top()) L_.push(num);
        else R_.push(num);
        if (L_.size() < R_.size()) {
            L_.push(R_.top());
            R_.pop();
        }else if (L_.size() - R_.size() == 2) {
            R_.push(L_.top());
            L_.pop();
        }
    }
    
    double findMedian() {
        if (L_.size() == R_.size()) 
            return (L_.top() + R_.top()) * 1.0 / 2;
        else return L_.top();
    }
    
private:
    priority_queue<int, vector<int>, less<int>> L_; // max_heap
    priority_queue<int, vector<int>, greater<int>> R_; // min_heap
};

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

二叉搜索树:

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder(): l_(m_.cend()), r_(m_.cend()) {}
    
    void addNum(int num) {
        if (m_.empty()) {
            l_ = r_ = m_.insert(num);
            return;
        }
        
        m_.insert(num);
        const size_t n = m_.size();
        if (n & 1) { // 奇数
            if (num >= *r_) l_ = r_; 
            else l_ = --r_;
        }else {
            if (num >= *r_) ++r_;
            else --l_;
        }
    }
    
    double findMedian() {
        return (*l_ + *r_) * 1.0 / 2;
    }
    
private:
    multiset<int> m_;
    multiset<int>::const_iterator l_;
    multiset<int>::const_iterator r_;
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值