/* 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