优先队列:实时判断数据流中第K大元素

703. Kth Largest Element in a Stream

Easy

255113FavoriteShare

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个的最大值:每次进来一个比K个值里面最小值大的数,踢出K个值里面最小的那个数,把最新的那个数记录进K个值里面(先排序,使用快排),快排的时间复杂度是KlogK,有k个值,所以该解法的复杂度为O(N*K(logK))

解法二:使用优先队列(priorityQueue)维持一个小顶堆(min heap)

java中的优先队列,priorityQueue的作用是保证每次取出的元素都是队列中权值最小的。其通过堆实现,具体说是通过完全二叉树(complete binary tree)实现的小顶堆(任意一个非叶子节点的权值,都不大于其左右子节点的权值)

import java.util.PriorityQueue;

public class KthLargest {

  final PriorityQueue<Integer> pq;
  final int k;

  public KthLargest(int k, int[] nums) {
    this.k = k;
    pq = new PriorityQueue<>(k);

    for(int i : nums){//对传进来的int数组遍历
      add(i);
    }
  }

  public int add(int val) {
    if(pq.size() < k)//如果队列中的数量少于K,直接添加入优先队列,优先队列会自动维持小顶堆
      pq.offer(val);
    else{
      if(pq.peek() < val){
      //否则队列中的数量大于或者等于K,优先队列中的最小数字小于新的数据,优先队列中的顶堆要被移除,并且添加入新的数据进优先队列
        pq.poll();
        pq.offer(val);
      }
    }
    return pq.peek();//返回当前第K大的数
  }
}

维持小顶堆的时间复杂度是,遍历的有N个数据,所以时间复杂度为O(Nlog2K)

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值