algorighm/leetcode/中等/数组中第k个最大值.js

164 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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
*/
// 思路1:排序之后直接取,但是不符合题目要求
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
const findKthLargest = function (nums, k) {
nums.sort((a, b) => a - b);
return nums[nums.length - k];
};
// 使用快速选择算法
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
const partition = (nums, left, right) => {
const pivot = nums[right];
let i = left;
for (let j = left; j < right; j++) {
if (nums[j] < pivot) {
[nums[i], nums[j]] = [nums[j], nums[i]];
i++;
}
}
[nums[i], nums[right]] = [nums[right], nums[i]];
return i;
};
const quickSelect = (nums, left, right, k) => {
if (left === right) return nums[left];
const pivotIndex = partition(nums, left, right);
if (pivotIndex === k) {
return nums[k];
} if (pivotIndex < k) {
return quickSelect(nums, pivotIndex + 1, right, k);
}
return quickSelect(nums, left, pivotIndex - 1, k);
};
const findKthLargest2 = function (nums, k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
};
// 使用最小堆
class MinHeap {
constructor() {
this.heap = [];
}
size() {
return this.heap.length;
}
peek() {
return this.heap[0];
}
insert(value) {
this.heap.push(value);
this.heapifyUp();
}
remove() {
if (this.size() === 1) {
return this.heap.pop();
}
const root = this.heap[0];
this.heap[0] = this.heap.pop();
this.heapifyDown();
return root;
}
heapifyUp() {
let index = this.size() - 1;
while (index > 0) {
const parentIndex = Math.floor((index - 1) / 2);
if (this.heap[parentIndex] <= this.heap[index]) break;
[this.heap[parentIndex], this.heap[index]] = [this.heap[index], this.heap[parentIndex]];
index = parentIndex;
}
}
heapifyDown() {
let index = 0;
const length = this.size();
const element = this.heap[0];
while (true) {
const leftChildIndex = 2 * index + 1;
const rightChildIndex = 2 * index + 2;
let leftChild; let
rightChild;
let swap = null;
if (leftChildIndex < length) {
leftChild = this.heap[leftChildIndex];
if (leftChild < element) {
swap = leftChildIndex;
}
}
if (rightChildIndex < length) {
rightChild = this.heap[rightChildIndex];
if ((swap === null && rightChild < element) || (swap !== null && rightChild < leftChild)) {
swap = rightChildIndex;
}
}
if (swap === null) break;
[this.heap[index], this.heap[swap]] = [this.heap[swap], this.heap[index]];
index = swap;
}
}
}
const findKthLargest3 = function (nums, k) {
const minHeap = new MinHeap();
for (const num of nums) {
minHeap.insert(num);
if (minHeap.size() > k) {
minHeap.remove();
}
}
return minHeap.peek();
};
// 示例测试
console.log(findKthLargest([3, 2, 1, 5, 6, 4], 2)); // 输出: 5
console.log(findKthLargest([3, 2, 3, 1, 2, 4, 5, 5, 6], 4)); // 输出: 4
console.log(findKthLargest2([3, 2, 1, 5, 6, 4], 2)); // 输出: 5
console.log(findKthLargest2([3, 2, 3, 1, 2, 4, 5, 5, 6], 4)); // 输出: 4
console.log(findKthLargest3([3, 2, 1, 5, 6, 4], 2)); // 输出: 5
console.log(findKthLargest3([3, 2, 3, 1, 2, 4, 5, 5, 6], 4)); // 输出: 4