Leetcode 295. 数据流的中位数 堆

原题链接: Leetcode 295. 数据流的中位数


中位数查找思想:用两个堆维护数据(大顶堆存左半部分数据,小顶堆存右半部分数据),堆顶分别为左半最大值和右半最小值,可 O (1) 获取中位数。

解法1:官解

cpp 复制代码
class MedianFinder {
public:
    //大顶堆存左半部分数据, 堆顶为左半最大值
    priority_queue<int, vector<int> ,less<int>> quemin;
    // 小顶堆存右半部分数据, 堆顶为右半最小值
    priority_queue<int, vector<int> ,greater<int>> quemax;
    MedianFinder() {
        
    }
    // 整个序列长度偶数:quemin长度=quemax长度
    // 整个序列长度奇数:quemin长度=quemax长度+1
    void addNum(int num) {
        if(quemin.empty() || num<=quemin.top()){
            quemin.push(num);
            if(quemax.size()+1<quemin.size()){
                quemax.push(quemin.top());
                quemin.pop();
            }
        }
        else{
            quemax.push(num);
            if(quemax.size()>quemin.size()){
                quemin.push(quemax.top());
                quemax.pop();
            }
        }
    }
    
    double findMedian() {
        if(quemin.size() > quemax.size()) return quemin.top();
        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();
 */

解法2:

参考: 如何自然引入大小堆?简洁写法!(Python/Java/C++/Go/JS/Rust)

  • 如果整个序列长度偶数:left长度 = right长度
  • 如果整个序列长度奇数:left长度 = right长度+1

加入数字的过程中, 要时时刻刻满足以上两个要求,就可以用 left 中的最大值以及 right 中的最小值计算中位数。

分类讨论:

  1. 如果当前 left 的大小和 right 的大小相等:
  • 如果添加的数字 num 比较大
  • 如果添加的数字 num 比较小
  1. 如果当前 left 比 right 多 1 个数:
  • 如果添加的数字 num 比较大
  • 如果添加的数字 num 比较小
cpp 复制代码
class MedianFinder {
public:
    //大顶堆存左半部分数据, 堆顶为左半最大值
    priority_queue<int, vector<int> ,less<int>> left;
    // 小顶堆存右半部分数据, 堆顶为右半最小值
    priority_queue<int, vector<int> ,greater<int>> right;
    MedianFinder() {
        
    }
    // 整个序列长度偶数:left长度=right长度
    // 整个序列长度奇数:left长度=right长度+1
    void addNum(int num) {
        if(left.size()==right.size()){
            right.push(num);
            left.push(right.top());
            right.pop();
        }
        else{
            left.push(num);
            right.push(left.top());
            left.pop();
        }
    }
    
    double findMedian() {
        if(left.size() > right.size()) return left.top();
        return (left.top()+right.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();
 */
相关推荐
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
To_OC3 天前
LC 994 腐烂的橘子:人人都说是 BFS 入门题,我却写了三遍才过
javascript·算法·leetcode
To_OC3 天前
LC 200 岛屿数量:经典 DFS 入门题,我第一次写居然连方向都搞错了
javascript·算法·leetcode
To_OC4 天前
LC 128 最长连续序列:别上来就排序,O (n) 解法才是这题的灵魂
javascript·算法·leetcode
To_OC6 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
To_OC7 天前
LC 1 两数之和:面试第一道必考题,暴力解法直接被面试官 pass
javascript·算法·leetcode
想吃火锅100513 天前
【leetcode】121.买卖股票的最佳时机js/c++
算法·leetcode·职场和发展
凌波粒13 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
退休倒计时13 天前
【每日一题】LeetCode 146. LRU 缓存 TypeScript
算法·leetcode·缓存·typescript