703. Kth Largest Element in a Stream

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

  • 解法一
    首先想到的方法,但是时间复杂度显然太高
/**
 * Created by liuchaoqun01 on 2019/1/12.
 */
public class KthLargest {

    private int k;

    private List arr;

    /**
     * 解法一: O(n2)
     * 但凡直接排序时间复杂度都不会小
     * @param k
     * @param nums
     */
    public KthLargest(int k, int[] nums) {
        this.k = k;
        if (arr == null) {
            arr = new ArrayList<>(k);
        }
        if (nums != null) {
            for (int a : nums) {
                arr.add(a);
            }
        }
    }
    public int add(int val) {
        arr.add(val);
        arr.sort(Comparator.reverseOrder());
        return arr.size() >= k ? arr.get(k - 1) : -1;
    }

    public static void main(String[] args) {
        int[] temp = {4,5,8,2};
        int k = 3;
        KthLargest kthLargest = new KthLargest(k, temp);
        System.out.println(kthLargest.add(3));
        System.out.println(kthLargest.add(5));
        System.out.println(kthLargest.add(10));
    }
  • 解法二:
    因为最后只关注第k大个数,因此只需要维护一个最小堆即可。

这道题让我们在数据流中求第K大的元素,跟之前那道Kth Largest Element in an Array很类似,但不同的是,那道题的数组是确定的,不会再增加元素,这样确定第K大的数字就比较简单。而这道题的数组是不断在变大的,所以每次第K大的数字都在不停的变化。那么我们其实只关心前K大个数字就可以了,所以我们可以使用一个最小堆来保存前K个数字,当再加入新数字后,最小堆会自动排序,然后把排序后的最小的那个数字去除,则堆中还是K个数字,返回的时候只需返回堆顶元素即可,参见代码如下:


/**
* 注意:这里一定时用小顶堆实现
 * Created by liuchaoqun01 on 2019/1/12.
 */
public class KthLargest2 {

    private int k;

    PriorityQueue minHeap;

    /**
     * 解法二: O(nlogk)
     * Time Complexity: KthLargest, O(n * logk). add O(logk). n = nums.length.
     * Space: O(k)
     * @param k
     * @param nums
     */
    public KthLargest2(int k, int[] nums) {
        this.k = k;
        this.minHeap = new PriorityQueue<>();
        for (int a : nums) {
            add(a);
        }
    }

    public int add(int val) {
        if (minHeap.size() < k) {
            minHeap.add(val);
        } else if (minHeap.peek() < val) {
            minHeap.poll();
            minHeap.add(val);
        }
        return minHeap.peek();
    }

    public static void main(String[] args) {
        int[] temp = {4,5,8,2};
        int k = 3;
        KthLargest2 kthLargest = new KthLargest2(k, temp);
        System.out.println(kthLargest.add(3));
        System.out.println(kthLargest.add(5));
        System.out.println(kthLargest.add(10));
    }
}
  • PriorityQueue:详解
    参考:
    1 深入理解Java PriorityQueue

你可能感兴趣的:(703. Kth Largest Element in a Stream)