设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。
你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中的初始元素。每次调用 KthLargest.add,返回当前数据流中第K大的元素。
示例:
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
解一:
因为在比较的数据流中的数据是固定的(K个元素比较),第一种方式就是每K个元素进行排序,排序的话用快排即可,时间复杂度是klogk,然后一共进行n-k次,所以整体的时间复杂度是O(nk*logk),
这个直接for循环,在循环内将k个元素排序即可,代码就不写了~
解二:
在固定的K个元素中查找第K大元素,我们可以维护一个小顶堆(堆顶的元素是最小的,也就是第K大元素),在K窗口每次向前移动时,新进入的元素会同堆顶元素比较,如果比堆顶元素还小,则不做任何操作;如果比堆顶元素大,则将堆顶元素移除,将新元素加入堆中并维护堆,整体下来时间复杂度为O(nlogk):
class KthLargest {
private PriorityQueue<Integer> q;
int k;
public KthLargest(int k, int[] nums) {
this.k = k;
q = new PriorityQueue(k);
for (int n : nums) {
add(n);
}
}
public int add(int val) {
if (q.size() < k) {
q.offer(val);
} else {
if (q.peek() < val) {
q.poll();
q.offer(val);
}
}
return q.peek();
}
}