设计一个找到数据流中第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
说明:
你可以假设 nums
的长度≥ k-1
且k
≥ 1。
我先想到的是一个比较简单的办法,但是效率比较低。
如果val的值小于result 则可以直接返回result,否则需要排序一次。
package com.Geeksun;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
class KthLargest {
private int k;
private List<Integer> list;
private Integer result; //用来记录第k大的值
public KthLargest(int k, int[] nums) {
list = new ArrayList<>();
this.k = k;
for(int i = 0;i < nums.length;i++){
list.add(nums[i]);
}
Collections.sort(list);
if(list.size() - k < 0){
result = null;
return;
}
result = list.get(list.size() - k);
}
public int add(int val) {
list.add(val);
if(result == null){
Collections.sort(list);
result = list.get(list.size() - k);
}
if(val <= result){
return result;
}else {
Collections.sort(list);
result = list.get(list.size() - k);
return result;
}
}
}
第二种方法是优先队列,具体的实现原理还没有去深究,这题的解法是,初始化一个容量为k的优先队列,若val的值比队头的最小元素大,则先出队队列头的元素,并将新的元素插入到优先队列中,新的元素会自动排序。
class KthLargest {
private int index;
private PriorityQueue<Integer> pq;
public KthLargest(int k, int[] nums)
{
index = k;
pq = new PriorityQueue<>(k); //注意此处的容量
for (int i : nums) {
addElement(i);
}
}
public int add(int val)
{
addElement(val);
return pq.peek();
}
private void addElement(int val)
{
if(pq.size() < index){
pq.add(val);
}else {
if(val > pq.peek()){
pq.poll();
pq.add(val);
}
}
}
}