From 333aec6eaa301d69be013fb8d01d6ed041e24221 Mon Sep 17 00:00:00 2001 From: = <--gbloal> Date: Wed, 22 May 2024 18:12:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=95=B0=E7=BB=84=E4=B8=AD=E7=AC=ACk?= =?UTF-8?q?=E4=B8=AA=E6=9C=80=E5=A4=A7=E5=80=BC(215)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- leetcode/中等/数组中第k个最大值.js | 163 +++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 leetcode/中等/数组中第k个最大值.js diff --git a/leetcode/中等/数组中第k个最大值.js b/leetcode/中等/数组中第k个最大值.js new file mode 100644 index 0000000..9640501 --- /dev/null +++ b/leetcode/中等/数组中第k个最大值.js @@ -0,0 +1,163 @@ +/* +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