703. 数据流中的第 K 大元素
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。
请实现 KthLargest 类:
KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。
示例:
输入:
[“KthLargest”, “add”, “add”, “add”, “add”, “add”]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
输出:
[null, 4, 5, 5, 8, 8]
解释:
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3); // return 4
kthLargest.add(5); // return 5
kthLargest.add(10); // return 5
kthLargest.add(9); // return 8
kthLargest.add(4); // return 8
思路
TOP K问题
根据题意,找的是 第K大 的元素,也就是说实际上是建立一个小根堆,堆中的元素是前K大的元素,并且堆顶是最小的,也是第K大的元素
class KthLargest {
int heap[];
int size = 0;
int count = 0;
public KthLargest(int k, int[] nums) {
heap = new int[k];
count = k;
for(int i : nums)add(i);
}
public int add(int val) {
if(size < count){
heap[size] = val;
up();
size ++;
}
else{
if(heap[0] < val){
//当前堆顶的元素不需要了,直接覆盖,因为只需要前K大的
heap[0] = val;
down();
}
}
return heap[0];
}
//上浮
public void up(){
int i = size;
int fa = (int)Math.ceil((i / 2.0 )) - 1;
while( fa >= 0 && heap[i] < heap[fa]){
int temp = heap[fa];
heap[fa] = heap[i];
heap[i] = temp;
i = fa;
fa = (int)Math.ceil((i / 2.0 )) - 1;
}
}
//下沉
public void down(){
int i = 0;
while( i * 2 + 1 < size){
//找出子结点中较小的节点
int child = i * 2 + 1;
if(child + 1 < size && heap[child] > heap[child + 1])child += 1;
if(heap[child] < heap[i]){
int temp = heap[child];
heap[child] = heap[i];
heap[i] = temp;
i = child;
}
//较小节点任然大于 当前节点,说明当前节点已经处于正确的位置
else
break;
}
}
}
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/