写点什么

手撸二叉树之数据流中的第 K 大元素

发布于: 4 小时前
手撸二叉树之数据流中的第 K 大元素

Hello, 大家好,今天是我参加 8 月更文的第 11 天,今天给大家带来的关于二叉树相关的算法题是数据流中的第 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
复制代码

解题思路

TopK 算法在面试中常问, 本题的解题思路如下:


  1. 使用大小为 k 的小根堆,在初始化的时候,保证堆中的元素个数不超过 K。

  2. 在每次 add() 的时候,将新元素 push() 到堆中,如果此时堆中的元素超过了 K,那么需要把堆中的最小元素(堆顶)pop()出来。

  3. 此时堆中的最小元素(堆顶)就是整个数据流中的第 K 大元素。


在本题中,我使用的是优先队列来存储前 K 大的元素,其中优先队列的队头为队列中最小的元素,也就是第 kk 大的元素。

代码实现

class KthLargest {    // 永远只记录 k 个值    PriorityQueue<Integer> pq;    int k;    public KthLargest(int k, int[] nums) {        this.k = k;        pq = new PriorityQueue<Integer>();        for (int i = 0; i < nums.length; i++) {            add(nums[i]);        }    }        public int add(int val) {        pq.offer(val);        // 如果队列的长度超过 K,则弹出        if(pq.size() > k){            pq.poll();        }        // 返回第k大的值        return pq.peek();    }}
复制代码

最后

复杂度分析


  • 时间复杂度:初始化时间复杂度为:O(nlogk) ,其中 n 为初始化时 nums 的长度;单次插入时间复杂度为:O(logk);

  • 空间复杂度:O(k)。需要使用优先队列存储前 k 大的元素。

发布于: 4 小时前阅读数: 3
用户头像

佛系编码 2019.05.13 加入

红鲤鱼与绿鲤鱼与驴。

评论

发布
暂无评论
手撸二叉树之数据流中的第 K 大元素