703. Kth Largest Element in a Stream(python+cpp)

本文介绍如何设计一个类来找到数据流中的第K大元素,通过使用堆数据结构,实现高效的查找和更新操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

Design a class to find the kth largest element in a stream. Note
that it is the kth largest element in the sorted order, not the kth
distinct element. Your KthLargest class will have a constructor
which accepts an integer k and an integer array nums, which
contains initial elements from the stream. For each call to the method
KthLargest.add, return the element representing the kth largest
element in the stream.
Example:

int k = 3; 
int[] arr = [4,5,8,2]; 
KthLargest kthLargest = new KthLargest(3, arr); 
kthLargest.add(3);   // returns 4
kthLargest.add(5);   // returns 5 
kthLargest.add(10);  // returns 5
kthLargest.add(9);   // returns 8 
kthLargest.add(4);   // returns 8

Note:
You may assume that nums’ length ≥ k-1 and k ≥ 1.

解释:
设计一个类,返回数据流中的最大的第k个元素。
注意是流中的,不是数组中的(215. Kth Largest Element in an Array(python+cpp)),如果是数组中的可以用快速排序中的partition做。
这道题目需要用堆来做
从小到大排序后总右往左数第k大的数字python的heap是小根堆,如果维持一个大小为k的heap的话,那么最小的数字(第一个数字)就是最终答案,后续输入的数字只需要和最小的数字nums[0]相比就好,如果当前的堆的大小小于k,则直接将新元素入堆,否则,当前的堆的大小一定是k(因为初始化的时候如果nums的长度大于k,已经将堆裁剪为大小为k的堆了),此时需要比较当前的valnums[0]的关系,如果小于就不管,如果大于就弹出堆中的最小值,将val入栈,python中可以直接用heapq.heapreplace(data,val),比先heap.pop()heapq.push()的速度要快得多。
需要有一个变量记录当前堆的大小。
python代码:

class KthLargest(object):

    def __init__(self, k, nums):
        """
        :type k: int
        :type nums: List[int]
        """
        self.data=nums
        self.k=k
        self.size=len(nums)
        heapq.heapify(self.data)
        while self.size>k:
            heapq.heappop(self.data)
            self.size-=1

    def add(self, val):
        """
        :type val: int
        :rtype: int
        """
        if self.size<self.k:
            heapq.heappush(self.data,val)
            self.size+=1
        elif val>self.data[0]:
            heapq.heapreplace(self.data,val)
        return self.data[0]
    
# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)

c++代码:

#include <algorithm> 
using namespace std;
class KthLargest {
public:
    int heap_size=0;
    int global_k=0;
    vector<int>global_nums;
    KthLargest(int k, vector<int> nums) {
        global_k=k;
        global_nums.assign(nums.begin(),nums.end());
        heap_size=nums.size();
        //c++默认是大根堆,这里需要用小根堆
        make_heap(global_nums.begin(),global_nums.end(),greater<int>());
        while (heap_size>k)
        {
            pop_heap(global_nums.begin(),global_nums.end(),greater<int>());
            global_nums.pop_back();
            heap_size--;
        }
    }
    
    int add(int val) {
        if (heap_size<global_k)
        {
            global_nums.push_back(val);
            push_heap(global_nums.begin(),global_nums.end(),greater<int>());
            heap_size++;
        }
        else if (val>global_nums[0])
        {
            pop_heap(global_nums.begin(),global_nums.end(),greater<int>());
            global_nums[global_k-1]=val;
            push_heap(global_nums.begin(),global_nums.end(),greater<int>());
        }
        return global_nums[0];
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest obj = new KthLargest(k, nums);
 * int param_1 = obj.add(val);
 */

总结:
1.虽然heapq.heapify(nums)以后nums并不是顺序的,但是nums[0]总是代表最小的元素(python heapq默认是小根堆,c++的小根堆也是这样)
但是如果想实现一个大顶堆怎么办?
把在数据进堆的时候把所有数据都取相反数,出来的时候再取一下相反数就可以啦。
2. STL 堆操作
头文件是#include <algorithm>
一般用到这四个:make_heap()pop_heap()push_heap()sort_heap();
(1)make_heap()构造堆
void make_heap(first_pointer,end_pointer,compare_function);
默认比较函数是(<),即最大堆。 函数的作用是将[begin,end)内的元素处理成堆的结构,要改成小根堆的时候,第三个参数变成greater<int>()
(2)push_heap()添加元素到堆
void push_heap(first_pointer,end_pointer,compare_function);
新添加一个元素在末尾,然后重新调整堆序。该算法必须是在一个已经满足堆序的条件下。 先在vector的末尾添加元素,再调用push_heap
(3)pop_heap()从堆中移出元素 ,
void pop_heap(first_pointer,end_pointer,compare_function);
把堆顶元素取出来,放到了数组或者是vector的末尾。 要取走,则可以使用底部容器(vector)提供的pop_back()函数。 先调用pop_heap再从vector中pop_back元素
(4)sort_heap()对整个堆排序 ,排序之后的元素就不再是一个合法的堆了。
注意push_heap()和pop_heap()的时候也要传入compare_function

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值