优先队列:实时判断数据流中第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)

猜你喜欢

转载自blog.csdn.net/haponchang/article/details/88975073
今日推荐