算法日常・每日刷题--<优先级队列>2

LCR 059. 数据流中的第 K 大元素 - 力扣(LeetCode)LCR 059. 数据流中的第 K 大元素 - 设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。请实现 KthLargest 类: * KthLargest(int k, int\[\] nums) 使用整数 k 和整数流 nums 初始化对象。 * int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。 示例:输入:"KthLargest", "add", "add", "add", "add", "add"\[3, \[4, 5, 8, 2], 3, 5, 10, 9, 4]输出:null, 4, 5, 5, 8, 8解释:KthLargest kthLargest = new KthLargest(3, 4, 5, 8, 2);kthLargest.add(3); // return 4kthLargest.add(5); // return 5kthLargest.add(10); // return 5kthLargest.add(9); // return 8kthLargest.add(4); // return 8 提示: * 1 <= k <= 104 * 0 <= nums.length <= 104 * -104 <= numsi <= 104 * -104 <= val <= 104 * 最多调用 add 方法 104 次 * 题目数据保证,在查找第 k 大元素时,数组中至少有 k 个元素 注意:本题与主站 703 题相同: https://leetcode.cn/problems/kth-largest-element-in-a-stream/ https://leetcode.cn/problems/kth-largest-element-in-a-stream/https://leetcode.cn/problems/jBjn9C/

一、题目描述

题目要求

设计一个可以持续接收数据流、快速返回第 K 大元素 的类 KthLargest,注意定义:将所有数字降序排序后,位于第 k 个位置的数,允许存在重复数字。 需要实现两个核心方法:

  1. 构造函数 KthLargest(int k, vector<int>& nums):给定 k 和初始数字流完成初始化;
  2. int add(int val):新增一个数字到数据流,返回当前全局第 k 大的值。

示例

输入:k=3,初始数组 [4,5,8,2] 依次调用 add(3)、add(5)、add(10)、add(9)、add(4) 输出:4,5,5,8,8 解释:

  • 初始数据流:[4,5,8,2],前 3 大数字 [4,5,8],第 3 大为 4;
  • 添加 3 后,前 3 大不变,返回 4;
  • 添加 5 后,前 3 大 [5,5,8],返回 5;
  • 添加 10 后,前 3 大 [5,8,10],返回 5;
  • 添加 9 后,前 3 大 [8,9,10],返回 8;
  • 添加 4 后,前 3 大不变,返回 8。

二,最优解法:固定容量小根堆(最小堆)

核心原理

我们只需要全局最大的 k 个数字,不需要存储全部数据:

  1. 使用小根堆,堆内最多保存 k 个元素;
  2. 堆的特性:堆顶是堆中最小值;
  3. 堆内存放当前前 k 大数字,堆顶天然就是全局第 k 大元素。

执行流程

  1. 初始化阶段:遍历所有初始数字,逐个入堆;若堆长度超过 k,弹出堆顶最小值(该数不属于前 k 大);
  2. add 新增数字:
    • 将新数字压入堆;
    • 若堆大小 > k,弹出堆顶最小元素;
    • 直接返回堆顶,即为当前第 k 大值。

为什么不用大根堆?

如果使用大根堆,会存储全部数据流,空间复杂度 O(n);且每次取第 k 大需要遍历堆,效率低下。小根堆仅存 k 个元素,空间、时间双重最优。

cpp 复制代码
class KthLargest {
    priority_queue<int ,vector<int>,greater<int>>heap;
    int _k; 
public:
    KthLargest(int k, vector<int>& nums) {
        _k=k;
        for(auto e:nums)
        {
            heap.push(e);
            if(heap.size()>_k)
            heap.pop();
        }
    }
    
    int add(int val) {
        heap.push(val);
        if(heap.size()>_k)
        heap.pop();
        return heap.top();

    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */
相关推荐
octopus_c4 小时前
STL 之 string:auto 与范围 for、常用接口、模拟实现与深浅拷贝
开发语言·c++·算法
老师我太想进步了202619 小时前
【数据结构-4】算法美学之顺序表
数据结构·算法
风影同志7832419 小时前
编码器是激活函数吗?—— 一个看起来很像、其实不是的类比
算法
UIU11420 小时前
P1481 魔族密码
c++·算法·动态规划
加宝的起点雷达1 天前
40 条候选里 38 条来自同一个源,主卡整屏重样
人工智能·算法·创业
秋天的怀念_David1 天前
算法一千零一夜 · 第二十六夜 协议的母语
java·spring boot·算法
闻缺陷则喜何志丹1 天前
【C++特性】四种类型转
c++·算法·类型转换
喵本喵叁肆1 天前
用 Boosting 把弱隐私算法炼成强隐私算法(英文原题:Boosting and Differential Privacy (FOCS 2010))
算法·集成学习·boosting