算法日常・每日刷题--<优先级队列>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);
 */
相关推荐
hanlin033 小时前
刷题笔记:力扣第189题-轮转数组
笔记·算法·leetcode
琥珀色糖3 小时前
leetcode hot100题(持续更新)移动零(双指针)
算法·leetcode·职场和发展·双指针·移动零
AndrewHZ4 小时前
【LLM技术全景】RAG 从原理到实战——检索增强生成完整指南
人工智能·深度学习·算法·llm·检索增强·生成式模型·rag
LuminousCPP4 小时前
单链表专题(三)-刷题复盘篇:从快慢指针到环形链表 II 数学推导
数据结构·经验分享·笔记·学习·算法·链表
-dzk-4 小时前
【贪心算法】LC 121.买卖股票的最佳时机
算法·贪心算法
hanlin034 小时前
动态规划专练:力扣第718、1143题
算法·leetcode·动态规划
ChaoZiLL4 小时前
二叉树经典例题
数据结构·算法
不正经学生4 小时前
C语言字符串函数进阶:安全版函数 + 错误处理 + 子串查找
c语言·开发语言·c++·算法·面试
三克的油5 小时前
算法基础-1
数据结构·c++·算法