给定整数数组nums和整数k,请返回数组中第k个最大的元素。
请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。
你必须设计并实现时间复杂度为O(n)的算法解决此问题。
解决方案
要求大小就要求排序,可以直接使用排序算法,但是这里要求O(n),一般的排序算法是达不到的。
方案一:手写一个大根堆
虽然jdk提供了PriorityQueue作为堆的实现,但是刷算法题直接调API也太low了。
但是这个方法内存占用太大了,毕竟堆是典型的空间换时间。
class Solution {
public int findKthLargest(int[] nums, int k) {
Heap heap = new Heap(nums.length);
for (int num : nums) {
heap.add(num);
}
int res = 0;
// 一共弹出k次,最后一次弹出的就是需要的第k大的数
for (int i = 0; i < k; i++) {
res = heap.poll();
}
return res;
}
class Heap {
// 存放数据的数组
private int[] heapArr;
// 堆的实时size(数组中有数据的位置是0~size-1)
private int size = 0;
// 堆的容量
private int capacity;
public Heap(int capacity) {
this.capacity = capacity;
this.heapArr = new int[capacity];
}
// 插入元素
public void add(int num) {
if(size == capacity) {
throw new ArrayIndexOutOfBoundsException("heap容量已满");
}
// 先将值插入到数组中的下一个空闲位置
heapArr[size++] = num;
// 需要调整堆的结构
insertHeapify(size-1);
}
// 弹出并删除顶部数据
public int poll() {
int res = heapArr[0];
// 将堆中的最后一个节点放到堆顶
heapArr[0] = heapArr[--size];
// 调整堆的结构
deleteHeapify();
return res;
}
// 返回顶部数据(不做删除)
public int peek() {
return heapArr[0];
}
/**
* 插入后进行调整
*/
private void insertHeapify(int cur) {
int parent = (cur - 1) / 2;
/**
* 后面一半的条件要看你要实现的时大根堆还是小根堆
*/
while (parent >= 0 && heapArr[parent] < heapArr[cur]) {
swap(parent, cur);
cur = parent;
parent = (cur - 1) / 2;
}
}
/**
* 该函数在末尾节点放到堆顶以后再调用,一定从堆顶开始
*/
private void deleteHeapify() {
int cur = 0;
int leftChild = (2 * cur) + 1;
int rightChild = (2 * cur) + 2;
// (每次循环都只对以cur和它的左右节点进行操作)
// 先判断有没有左孩子(右孩子的index一定比左孩子的index大1,如果左孩子都不存在右孩子就没有判断的必要)
while (leftChild < size) {
int maxChild = leftChild;
// 如果右孩子存在并且还比左孩子大,就让右孩子成为maxChild
if(rightChild < size && heapArr[rightChild] > heapArr[leftChild]) {
maxChild = rightChild;
}
// 上面的操作是在寻找最大的孩子,这里将父亲节点与最大的孩子进行比较
// 只有父亲节点小于子节点才需要向下交换,如果父亲节点已经是最大的了就不需要再继续循环
/** 当然这里是大根堆,如果是小根堆父亲节点大于子节点才向下交换 */
if(heapArr[cur] < heapArr[maxChild]) {
swap(cur, maxChild);
cur = maxChild;
leftChild = (2 * cur) + 1;
rightChild = (2 * cur) + 2;
} else {
break;
}
}
}
private void swap(int i, int j) {
int temp = heapArr[i];
heapArr[i] = heapArr[j];
heapArr[j] = temp;
}
}
}