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.
Implement KthLargest class:
KthLargest(int k, int[] nums) Initializes the object with the integer k and the stream of integers numsint add(int val) Appends the integer val to the stream and returns the element representing the kth largest element in the streamInput:
["KthLargest", "add", "add", "add", "add", "add"]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
Output:
[null, 4, 5, 5, 8, 8]
Explanation:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3); // return 4 (stream: [2,3,4,5,8], 3rd largest = 4)
kthLargest.add(5); // return 5 (stream: [2,3,4,5,5,8], 3rd largest = 5)
kthLargest.add(10); // return 5 (stream: [2,3,4,5,5,8,10], 3rd largest = 5)
kthLargest.add(9); // return 8 (stream: [2,3,4,5,5,8,9,10], 3rd largest = 8)
kthLargest.add(4); // return 8 (stream: [2,3,4,4,5,5,8,9,10], 3rd largest = 8)
Key Insight: We don't need to track ALL elements, only the k largest elements!
Use a min-heap of size k:
Why this works: If we maintain exactly k largest elements, the smallest of these k elements IS the kth largest!
This is a Min-Heap with Fixed Size problem:
Initialize:
Add Operation:
Time Complexity:
Why not max-heap? Max-heap gives us largest element, but we need kth largest. Min-heap's root naturally gives us the "boundary" element.
Init Time: O(n log k) where n = len(nums)
Add Time: O(log k)
Space: O(k)
Much better than sorting stream every time: O(n log n) per add!
1import java.util.PriorityQueue;
2
3class KthLargest {
4 private int k;
5 private PriorityQueue<Integer> minHeap;
6
7 public KthLargest(int k, int[] nums) {
8 this.k = k;
9 this.minHeap = new PriorityQueue<>();
10
11 // Add all elements to heap
12 for (int num : nums) {
13 minHeap.offer(num);
14 }
15
16 // Maintain heap size of k by removing smallest elements
17 while (minHeap.size() > k) {
18 minHeap.poll();
19 }
20 }
21
22 public int add(int val) {
23 // Add to heap if size < k
24 if (minHeap.size() < k) {
25 minHeap.offer(val);
26 }
27 // If val is larger than smallest in heap, replace it
28 else if (val > minHeap.peek()) {
29 minHeap.poll();
30 minHeap.offer(val);
31 }
32
33 // Root of min-heap is kth largest
34 return minHeap.peek();
35 }
36}
37