Leetcode-215-数组中的第K个最大元素📌
215. 数组中的第K个最大元素
给定整数数组 nums
和整数 k
,请返回数组中第 **k**
个最大的元素。
请注意,你需要找的是数组排序后的第 k
个最大的元素,而不是第 k
个不同的元素。
你必须设计并实现时间复杂度为 O(n)
的算法解决此问题。
示例 1:
输入: [3,2,1,5,6,4], k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4
提示:
1 <= k <= nums.length <= 105
-104 <= nums[i] <= 104
解题思路
使用排序或优先队列解题。
// 排序 时间复杂度O(nlogn)
function findKthLargest(nums: number[], k: number): number {
if (nums.length === 0) return 0
nums.sort((a, b) => a - b)
return nums[nums.length - k]
};
// 优先队列
class CustomPriorityQueue<T> {
private data: T[] = [];
private compare: (a: T, b: T) => number;
constructor(compare: (a: T, b: T) => number) {
this.compare = compare;
}
// 返回队列中元素的数量
size(): number {
return this.data.length;
}
// 将一个元素插入队列中
offer(item: T) {
this.data.push(item);
this.bubbleUp(this.data.length - 1);
}
// 弹出队列中最小的元素(即根节点),并返回该元素。如果队列为空,则返回undefined。
poll(): T | undefined {
if (this.data.length === 0) {
return undefined;
}
const result = this.data[0];
const last = this.data.pop();
if (this.data.length > 0 && last !== undefined) {
this.data[0] = last;
this.bubbleDown(0);
}
return result;
}
// 返回队列中最小的元素(即根节点),但不弹出该元素。如果队列为空,则返回undefined。
peek(): T | undefined {
return this.data.length > 0 ? this.data[0] : undefined;
}
// 指定位置的元素(索引为index)上浮到合适的位置,以维护小根堆的性质。
private bubbleUp(index: number) {
const item = this.data[index];
while (index > 0) {
const parentIndex = Math.floor((index - 1) / 2);
const parent = this.data[parentIndex];
if (this.compare(item, parent) >= 0) {
break;
}
this.data[index] = parent;
index = parentIndex;
}
this.data[index] = item;
}
// 将指定位置的元素(索引为index)下沉到合适的位置,以维护小根堆的性质。
private bubbleDown(index: number) {
const item = this.data[index];
const lastIndex = this.data.length - 1;
while (true) {
const leftChildIndex = index * 2 + 1;
const rightChildIndex = index * 2 + 2;
let swapIndex = -1;
if (leftChildIndex <= lastIndex) {
const leftChild = this.data[leftChildIndex];
if (this.compare(leftChild, item) < 0) {
swapIndex = leftChildIndex;
}
}
if (rightChildIndex <= lastIndex) {
const rightChild = this.data[rightChildIndex];
if ((swapIndex === -1 && this.compare(rightChild, item) < 0) ||
(swapIndex !== -1 && this.compare(rightChild, this.data[swapIndex]) < 0)) {
swapIndex = rightChildIndex;
}
}
if (swapIndex === -1) {
break;
}
this.data[index] = this.data[swapIndex];
index = swapIndex;
}
this.data[index] = item;
}
}
function findKthLargest(nums: number[], k: number): number {
// 默认是小根堆 复杂度 空间:O(k). 时间 nlogk
const minHeap = new CustomPriorityQueue<number>((a, b) => a - b);
for (let i = 0; i < nums.length; i++) {
if (minHeap.size() < k) {
minHeap.offer(nums[i]);
} else if (minHeap.peek() < nums[i]) {
minHeap.poll();
minHeap.offer(nums[i]);
}
}
return minHeap.peek();
};