一、题目描述
设计一个找到数据流中第 k 大元素的类(class)。注意是排序后的第 k 大元素,不是第 k 个不同的元素。
请实现 KthLargest 类:
KthLargest(int k, int[] nums) 使用整数 k 和整数流 nums 初始化对象。
int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。
二、分析
设计一个找到数据流中第 k 大元素的类
- 需要我们找到经过排序的数据流中的第K个元素,从大到小排。
- 我们可以采用小顶堆来存储数据流,当堆数量超过K时,我们将顶部元素出堆,弹出最小元素,保证剩下的数据都是最大的数据。
三、实现
public KthLargest(int k, int[] nums) {
//建立小顶堆
this.k = k;
minHeap = new heap();
for (int x : nums) {
add(x);
}
}
public int add(int val) {
minHeap.insert(val);
if (minHeap.size() > this.k) {
minHeap.pop();
}
return minHeap.peek();
}
class heap {
private int [] heapArr;
private int size=0;
public heap(){
heapArr=new int[8];
}
public heap(int num){
heapArr=new int[num];
}
public heap(int [] arr){
heapArr=arr;
build(arr);
}
public int size(){
return size;
}
/**
* 1.从最后一个父节点开始进行沉降即可
* @param arr
*/
private void build(int [] arr){
for(int i=arr.length/2 - 1;i>=0;i--){
sinkDown(i);
}
}
/**
* 1.插入到最后的那个元素,如果大小已经和数组一样大,则进行扩容
* 2.执行元素校验,检查插入元素是否符合堆的特性,不符合则进行调整,插入采用上浮操作
*/
public void insert(int des){
if(size>=heapArr.length){
resize();
}
heapArr[size]=des;
floatUp(size);
size++;
}
/**
* 1.交换堆底元素与堆顶元素,为了保持堆的完全二叉树结构,从底部交换方便处理一些
* 2.弹出堆底部元素,从对顶开始下沉
*/
public int pop(){
if(size<0){
return -1;
}
int temp=heapArr[0];
heapArr[0]=heapArr[size-1];
size--;
//下沉
sinkDown(0);
return temp;
}
public int peek(){
return heapArr[0];
}
public void resize(){
heapArr= Arrays.copyOf(heapArr, heapArr.length*2);
}
/**
* 大顶堆,父元素最大
* 小顶堆,父元素最小
* 我们以小顶堆为例
* 1.与父元素比较,双亲(parent)下标 = (child - 1) / 2;
* 2.交换两者的位置
* 3.检查父元素是否符合要求
* @param index
*/
private void floatUp(int index){
if(index<0){
return;
}
int parent=(index-1)/2;
if(heapArr[parent]>heapArr[index]){
int temp=heapArr[parent];
heapArr[parent]=heapArr[index];
heapArr[index]=temp;
//检查父元素是否符合要求
floatUp(parent);
}
}
/**
* 大顶堆,父元素最大
* 小顶堆,父元素最小
* 我们以小顶堆为例
* 左孩子(left)下标 = 2 * parent + 1;
* 右孩子(right)下标 = 2 * parent + 2
*
* 1.检查两个子元素与父元素比较
*
* @param parent
*/
private void sinkDown(int parent){
if(parent<0||parent>size/2 - 1){
return;
}
int leftChild=2 * parent + 1;
int rightChild=2 * parent + 2;
int minIndex;
if(heapArr[leftChild]>heapArr[rightChild]){
minIndex=rightChild;
}else{
minIndex=leftChild;
}
//父元素大于子元素的话则进行交换
if(heapArr[parent]>heapArr[minIndex]){
int temp=heapArr[parent];
heapArr[parent]=heapArr[minIndex];
heapArr[minIndex]=temp;
sinkDown(minIndex);
}
}
}