【题解】力扣703.数据流中的第K大元素
题目来源
题目描述:
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。
请实现 KthLargest 类:
-
KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
-
int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。
思路及算法
方法一:优先队列
可以使用一个大小为\(k\)的优先队列来存储前\(k\)大的元素,其中优先队列的队头为队列中最小的元素,也就是第\(k\)大的元素
在单次操作中,先将元素加入到优先队列中,如果当前队列的长度大于\(k\),则将队头元素弹出,以保证优先队列的大小为\(k\)。
class KthLargest {
PriorityQueue<Integer> heap; // 声明
int k = 0;
public KthLargest(int k, int[] nums) { // 构造方法
this.k = k;
heap = new PriorithQueue<Integer>(k); // 实例化优先队列对象,分配对象
for(int i : nums)
add(i);
}
public int add(int val) {
if(heap.size() < k){
heap.offer(val); // 将val插入到优先队列中
}else if (heap.peek() < val){ // 如果头部元素小于当前要插入的值
heap.poll(); // 检索并删除队列的头部,如果头部为空,则返回null
heap.offer(val);
}
return heap.peek(); // 检索但不删除队列的头部,如果头部为空,则放回null
}
}
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/
方法二:堆排序
- 使用大小为
K
的小根堆,在初始化的时候,保证堆中的元素个数不超过K
。 - 在每次
add()
的时候,将新元素push()
到堆中,如果此时堆中的元素超过了K
,那么需要把堆中的最小元素(堆顶)pop()
出来。 - 此时堆中的最小元素(堆顶)就是整个数据流中的第
K
大元素。
class KthLargest {
// 堆排序解法 - 维护一个大小为k的小根堆, 若当前要插入的数小于等于堆顶元素, 则丢弃; 否则插入, 可以直接插入到堆顶, 在进行调整. 堆顶元素保存了第k大元素.
// 创建一个小根堆
int[] heap;
int size = 0;
int count = 0;
public KthLargest(int k, int[] nums) { // 构造方法
heap = new int[k];
count = k;
// 初始化一个大小为k的小根堆
for (int i = 0; i < nums.length; i++) {
add(nums[i]);
}
}
public int add(int val) {
if (size < count) {
heap[size] = val;
up(size);
size++;
} else if (heap[0] < val) {
heap[0] = val;
down(0);
}
return heap[0];
}
// 自上向下调整堆,下沉
public void down (int u) {
int t = u;
if (2 * u + 1 < size && heap[2 * u + 1] < heap[t])
t = 2 * u + 1;
if (2 * u + 2 < size && heap[2 * u + 2] < heap[t])
t = 2 * u + 2;
if (t != u) {
int temp = heap[u];
heap[u] = heap[t];
heap[t] = temp;
down (t);
}
}
// 自下向上调整堆,上升
public void up (int u) {
// 存在父亲节点, 并且父亲节点的值大于当前值, 则进行交换
while ((int)(Math.ceil(u / 2.0) - 1) >= 0 && heap[(int)Math.ceil(u / 2.0) - 1] > heap[u]) {
int p = (int)(Math.ceil(u / 2.0) - 1);
int temp = heap[u];
heap[u] = heap[p];
heap[p] = temp;
u = p;
}
}
}
/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest obj = new KthLargest(k, nums);
* int param_1 = obj.add(val);
*/