Open azl397985856 opened 2 years ago
class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: n = len(nums) def quick_find(start, end):
#这是类快排,大体和快排相同但做了适当优化
nonlocal n
pivot = start
left, right = start, end
while left < right:
while left < right and nums[right] >= nums[pivot]: right -= 1 # 如果当前值大于nums[pivot]的值,就继续往左找,直到发现小于的值
while left < right and nums[left] <= nums[pivot]: left += 1
nums[left], nums[right] = nums[right], nums[left]
nums[pivot], nums[right] = nums[right], nums[pivot] # 此时,pivot左边的数都比nums[pivot]小。同理,右边的都比nums[pivot]大
if right == n - k:
return nums[right] # 此时说明发现了第k大的数,返回
elif right < n - k:
return quick_find(right + 1, end) # 说明第k大的数在右半边,只排右边的
else:
return quick_find(start, right - 1) # 同理,只排左边的
return quick_find(0, n - 1)
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
heap=nums[:k]
heapq.heapify(heap)
for num in nums[k:]:
if num > heap[0]:
heapq.heapreplace(heap,num)
return heap[0]
Time: O(nlogk)
Space: O(k)
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
import heapq
h = []
for i in nums:
heapq.heappush(h, i)
m = len(nums)-k
while m > 0:
heapq.heappop(h)
m -= 1
return heapq.heappop(h)
class 数组中的第K个最大元素_215 {
public int findKthLargest(int[] nums, int k) {
int[] minHeapData = new int[k];
System.arraycopy(nums, 0, minHeapData, 0, k);
MinHeap heap = new MinHeap(minHeapData);
for(int i = k; i < nums.length; i ++) {
heap.add(nums[i]);
}
return heap.getMin();
}
private class MinHeap{
private int[] data;
public MinHeap(int[] data){
this.data = data;
// 从最小的非叶子节点开始 倒序调整堆
for(int i = (data.length - 1) >> 1 ; i >= 0; i--) heapify(i);
}
private void heapify(int i) {
int r = (i + 1) << 1;
int l = r - 1;
int smallest = i;
if(r < data.length && data[smallest] > data[r]) smallest = r;
if(l < data.length && data[smallest] > data[l]) smallest = l;
if(smallest == i) return;
swap(data, smallest, i);
heapify(smallest);
}
private void swap(int[] data, int a, int b) {
int temp = data[a];
data[a] = data[b];
data[b] = temp;
}
public void add(int i) {
if(data[0] < i) { // 小根堆 更大的才能放进去
data[0] = i;
heapify(0);
}
}
public int getMin() {
return data[0];
}
}
}
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
const findKthLargest = function(nums, k) {
const minHeap = new BinaryHeap((c, p) => c > p);
for (const num of nums) {
minHeap.push(num);
if (minHeap.size() > k) {
minHeap.pop();
}
}
return minHeap.pop();
};
var findKthLargest = function(nums, k) { return nums.sort((a,b)=>a-b)[nums.length-k] };
class Solution {
public:
void maxHeapify(vector<int>& a, int i, int heapSize) {
int l = i * 2 + 1, r = i * 2 + 2, largest = i;
if (l < heapSize && a[l] > a[largest]) {
largest = l;
}
if (r < heapSize && a[r] > a[largest]) {
largest = r;
}
if (largest != i) {
swap(a[i], a[largest]);
maxHeapify(a, largest, heapSize);
}
}
void buildMaxHeap(vector<int>& a, int heapSize) {
for (int i = heapSize / 2; i >= 0; --i) {
maxHeapify(a, i, heapSize);
}
}
int findKthLargest(vector<int>& nums, int k) {
int heapSize = nums.size();
buildMaxHeap(nums, heapSize);
for (int i = nums.size() - 1; i >= nums.size() - k + 1; --i) {
swap(nums[0], nums[i]);
--heapSize;
maxHeapify(nums, 0, heapSize);
}
return nums[0];
}
};
min heap
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
// lower values are considered of higher priority and come out of the pq earlier
priority_queue<int, vector<int>, greater<int>> pq;
for(int i = 0; i < nums.size(); ++i) {
if (pq.size() < k) {
pq.push(nums[i]);
} else {
if (nums[i] > pq.top()) {
pq.pop();
pq.push(nums[i]);
}
}
}
return pq.top();
}
};
AC
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> heap = new PriorityQueue<>();
for(int i = 0;i < nums.length;i++){
if(heap.size() < k){
heap.add(nums[i]);
} else if(heap.peek() < nums[i]){
heap.poll();
heap.add(nums[i]);
}
}
return heap.poll();
}
}
time: O(N*logN) space: O(K)
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
for(int val: nums){
queue.add(val);
if(queue.size() > k){
queue.poll();
}
}
return queue.peek();
}
}
title: "Day 85 215. 数组中的第K个最大元素" date: 2021-12-03T22:29:54+08:00 tags: ["Leetcode", "c++", "heap"] categories: ["91-day-algorithm"] draft: true
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 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 <= 104
-104 <= nums[i] <= 10^4
- 1、今日题目是很好的题目,一个复习快排的思想,一个复习如何建立堆。
class Solution{
public:
void heap_sort(vector<int>&ans, int i, int n) {
int l = i * 2 + 1, r = i * 2 + 2, max = i;
if (l < n && ans[l] > ans[max]) max = l;
if (r < n && ans[r] > ans[max]) max = r;
if (max != i)
{
swap(ans[i], ans[max]);
heap_sort(ans, max, n);
}
}
void buildHeap(vector<int>& ans, int n) {
for (int i = n / 2; i >= 0; --i) heap_sort(ans, i, n);
}
}
int findKthLargest(vector<int>& nums, int k) {
int n = nums.size();
buildHeap(nums, n);
for (int i = nums.size() - 1; i >= nums.size() - k + 1; i--)
{
swap(nums[0], nums[i]);
--n;
heap_sort(nums, 0, n);
}
return nums[0];
}
};
func findKthLargest(nums []int, k int) int {
nums = heapSort(nums)
return nums[k-1]
}
func heapSort(nums []int) []int {
lens := len(nums)
// 先建立一个堆
buildHeap(nums,lens)
// 上面构建堆后,其实已经满足了基本的 最大堆或者最小堆
// 此时根节点肯定是最大值或者最小值了
// 从数组最后挨个往前遍历
for i:=lens-1;i>=0;i-- {
// 构成堆后的数组的第一个值和最后一个值进行替换
// 然后把 数组 i 个值之后的数之外的数 继续构建堆
// 循环往复
swap(nums,0,i)
lens -= 1
heap(nums,0,lens)
}
return nums
}
// 构建一个堆
func buildHeap(nums []int,lens int) {
// 一般数组长度的一半 很可能就不是叶子节点了,但可以确定的是 数组长度一半后面的肯定都是叶子节点
// 叶子节点是最底下的节点了,所以不需要往下置换了,所以从 长度/2开始算
for i := lens/2;i>=0;i-- {
heap(nums,i,lens)
}
}
func heap(nums []int,i,lens int) {
// 每个父节点的左节点 是当前数组下标i的 2*i + 1
// 每个父节点的右节点 是当前数组下标i的 2*i + 2
left := 2*i + 1
right := 2*i + 2
// 咱们做最小堆,也就是小的数组排在后面
// 假设当前的 父节点是最小
min := i
// 当 父节点的左子节点 小于 数组总长度 且 左子节点的值小于父节点的时候,所以这个小堆里 左子节点是最小的(暂时不替换)
// 为什么要 父节点的左子节点 小于 数组总长度, 因为如果父节点的左子节点比 数组总长度还长,那说明 超出了数组范围了..说明该父节点其实没有左子节点
if left < lens && nums[left] < nums[min] {
min = left
}
// 右子节点跟上面左子节点一个道理
if right < lens && nums[right] < nums[min] {
min = right
}
// 如果通过上面与左右子节点相比,最小值已经不是当初的父节点了
// 那么把最小的节点与父节点进行变换,变换后可能会影响该父节点的子节点的子节点,所以还得往下继续对比比换一下
if min != i {
swap(nums,min,i)
heap(nums,min,lens)
}
}
func swap(arr []int,m,n int) []int {
arr[m],arr[n] = arr[n],arr[m]
return arr
}
TopN问题,优先队列
class Solution {
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
PriorityQueue<Integer> queue = new PriorityQueue<>(k);
for (int i = 0; i < n; i++) {
if (queue.size() < k) {
queue.offer(nums[i]);
} else if (nums[i] > queue.peek()) {
queue.poll();
queue.offer(nums[i]);
}
}
return queue.peek();
}
}
javascript
/*
* @lc app=leetcode.cn id=215 lang=javascript
*
* [215] 数组中的第K个最大元素
*/
// @lc code=start
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var findKthLargest = function(nums, k) {
const heap = new Heap(nums.slice(0, k), 'min')
for (let i = k; i < nums.length; i++) {
const ele = nums[i];
if (ele > heap.peek()) {
heap.set(0, ele)
heap.heapifyDown()
}
}
return heap.peek()
};
class Heap {
constructor(arr = [], type = 'min') {
this.size = 0
this.heap = []
this.type = type
for (let i = 0; i < arr.length; i++) {
const ele = arr[i];
this.add(ele)
}
}
/**
* 修改堆的值
* @param {Number} index 设置的索引值,不能超过size
* @param {Number}} value 设置的值
*/
set(index, value) {
if (index > this.size - 1) {
return
}
this.heap[index] = value
}
/**
* 添加值
* @param {Number} value 待添加的值
*/
add(value) {
this.heap.push(value)
this.size = this.heap.length
this.heapifyUp()
}
/**
* 取出堆顶
*/
poll() {
if (this.size === 0) {
return
}
const target = this.heap[0]
this.heap[0] = this.heap[this.size - 1]
this.size--
this.heap.length = this.size
this.heapifyDown()
return target
}
/**
* 获取堆顶的值
*/
peek() {
if (this.size === 0) {
return
}
const target = this.heap[0]
return target
}
/**
* 向堆顶堆化
*/
heapifyUp() {
let index = this.size - 1
while (this.hasParent(index) && this.compare(this.getParent(index), this.heap[index])) {
this.swap(this.getParentIndex(index), index)
index = this.getParentIndex(index)
}
}
/**
* 向下比较
*/
heapifyDown() {
let index = 0;
while (this.hasLeftChild(index)) {
let nextIndex = this.getLeftChildIndex(index)
if (this.hasRightChild(index) && this.compare(this.rightChild(index), this.leftChild(index), 'index')) {
nextIndex = this.getRightChildIndex(index)
}
if (this.compare(this.heap[index], this.heap[nextIndex])) {
this.swap(index, nextIndex);
} else {
break
}
index = nextIndex
}
}
/**
* 根据堆类型来比较值或者索引值
* @param {Number} first 比较的值
* @param {Number} second 另一个比较的值
* @param {String} compareType 比较的类型,值或者索引值
*/
compare(first, second, compareType) {
if (compareType === 'index') {
if (this.type === 'min') {
return first < second
} else {
return first > second
}
} else {
if (this.type === 'min') {
return first > second
} else {
return first < second
}
}
}
/**
* 交换两个索引之间的值
* @param {Number} target 交换索引
* @param {Number} source 另一个交换索引
*/
swap(target, source) {
const temp = this.heap[source]
this.heap[source] = this.heap[target]
this.heap[target] = temp
}
getLeftChildIndex(parentIndex) {
return 2 * parentIndex + 1;
}
getRightChildIndex(parentIndex) {
return 2 * parentIndex + 2;
}
getParentIndex(childIndex) {
return Math.trunc((childIndex - 1) / 2);
}
hasLeftChild(index) {
return this.getLeftChildIndex(index) < this.size;
}
hasRightChild(index) {
return this.getRightChildIndex(index) < this.size;
}
hasParent(index) {
return this.getParentIndex(index) >= 0;
}
leftChild(parentIndex) {
return this.heap[this.getLeftChildIndex(parentIndex)];
}
rightChild(parentIndex) {
return this.heap[this.getRightChildIndex(parentIndex)];
}
getParent(childIndex) {
return this.heap[this.getParentIndex(childIndex)];
}
}
// @lc code=end
C++ Code:
class Solution {
public:
int quicksort(vector<int>& nums, int l, int r, int idx)
{
int res = randpartition(nums, l, r);
if(res == idx)
return res;
else if(res < idx)
return quicksort(nums,res+1,r,idx);
else
return quicksort(nums,l,res-1,idx);
}
int randpartition(vector<int>& nums, int l, int r)
{
int i = rand()%(r-l+1)+l;
swap(nums[i], nums[r]);
return partition(nums, l, r);
}
int partition(vector<int>& nums, int l, int r)
{
int i = l;
for(int j=l;j<r;++j)
if(nums[j]<nums[r])
{
swap(nums[i],nums[j]);
++i;
}
swap(nums[i],nums[r]);
return i;
}
int findKthLargest(vector<int>& nums, int k) {
srand(time(NULL));
return nums[quicksort(nums,0,nums.size()-1,nums.size()-k)];
}
};
堆排序
import heapq as h
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
heap = []
for num in nums:
# 如果堆长度没到k,无脑塞
if len(heap) < k:
h.heappush(heap, num)
else:
# 如果长度到k了,且当前元素比堆顶要大,我们才加进去,当然要先把最小的pop出来再加!
if num > heap[0]:
h.heappop(heap)
h.heappush(heap, num)
return h.heappop(heap)
class Solution {
public:
int findKthLargest(vector<int> &nums, int k) {
int size = nums.size();
sort(begin(nums), end(nums));
return nums[size - k];
}
};
class Solution {
Random random = new Random();
public int findKthLargest(int[] nums, int k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}
public int quickSelect(int[] a, int l, int r, int index) {
int q = randomPartition(a, l, r);
if (q == index) {
return a[q];
} else {
return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
}
}
public int randomPartition(int[] a, int l, int r) {
int i = random.nextInt(r - l + 1) + l;
swap(a, i, r);
return partition(a, l, r);
}
public int partition(int[] a, int l, int r) {
int x = a[r], i = l - 1;
for (int j = l; j < r; ++j) {
if (a[j] <= x) {
swap(a, ++i, j);
}
}
swap(a, i + 1, r);
return i + 1;
}
public void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue
for(int i = 0;i < nums.length;i++){
if(heap.size() < k){
heap.add(nums[i]);
} else if(heap.peek() < nums[i]){
heap.poll();
heap.add(nums[i]);
}
}
return heap.poll();
}
}
public class KthLargestNumber {
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
int targetIndex = n - k;
int start = 0, end = n - 1;
while (true) {
int index = partition(nums, start, end);
if (index == targetIndex) {
return nums[targetIndex];
} else if (index > targetIndex) {
end = index - 1;
} else {
start = index + 1;
}
}
}
private int partition(int[] nums, int start, int end) {
int pivot = start, l = start + 1, r = end;
while (l <= r) {
if (nums[l] > nums[pivot] && nums[r] < nums[pivot]) {
swap(nums, l, r);
l++;
r--;
}
if (nums[l] <= nums[pivot]) {
l++;
}
if (nums[r] >= nums[pivot]) {
r--;
}
}
swap(nums, pivot, r);
return r;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
https://leetcode.com/submissions/detail/596613783/
var findKthLargest = function (nums, k) {
return quickSelect(nums, 0, nums.length - 1, k);
};
function quickSelect(arr, start, end, k) {
const pivotIndex = partition(arr, start, end);
if (k < arr.length - pivotIndex) {
return quickSelect(arr, pivotIndex + 1, end, k);
} else if (k > arr.length - pivotIndex) {
return quickSelect(arr, start, pivotIndex - 1, k);
}
return arr[pivotIndex];
}
function partition(arr, start, end) {
const pivot = arr[end];
let i = start;
let j = end - 1;
while (i <= j) {
while (arr[i] < pivot) {
i += 1;
}
while (arr[j] > pivot) {
j -= 1;
}
if (i <= j) {
swap(arr, i, j);
i += 1;
j -= 1;
}
}
swap(arr, i, end);
return i;
}
function swap(arr, i, j) {
[arr[i], arr[j]] = [arr[j], arr[i]];
}
思路 大顶堆,取出K-1,剩下就是K大 代码(C++)
实现语言: C++
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int res;
priority_queue<int> q;
for (auto& num : nums)
q.push(num);
while (!q.empty() && k > 1)
{
auto top = q.top();
q.pop();
k--;
}
res = q.top();
return res;
}
};
复杂度分析 时间复杂度: O(NlogN) 空间复杂度: O(N)
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int res;
priority_queue<int> q;
for (auto& num : nums)
q.push(num);
while (!q.empty() && k > 1)
{
auto top = q.top();
q.pop();
k--;
}
res = q.top();
return res;
}
};
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
nums.sort(reverse = True)
return nums[k - 1]
To find the kth largest element in the array, we could use a k-sized min-heap. Min-headp store the largest k numbers, since it is a min heap, the top of the heap would be the kth largest.
class Solution {
public:
void swap(int& a, int& b) {
if (a != b) {
a ^= b;
b ^= a;
a ^= b;
}
}
void heapify(vector<int>& heap) {
int n = heap[0];
for (int i = n / 2; i >= 1; i--) {
top_down(heap, i);
}
}
void top_down(vector<int>& heap, int index) {
int n = heap[0];
while (index <= n / 2) {
int minChild = getMinChildIndex(heap, index);
if (heap[index] <= heap[minChild])
break;
swap(heap[index], heap[minChild]);
index = minChild;
}
}
int getMinChildIndex(vector<int>& heap, int index) {
int l = index * 2;
int r = index * 2 + 1;
if (r > heap[0] || heap[l] < heap[r])
return l;
return r;
}
void heap_push(vector<int>& heap, int v) {
int n = heap[0];
heap[n + 1] = v;
int index = ++heap[0];
while (index > 1 && heap[index] < heap[index / 2]) {
swap(heap[index], heap[index / 2]);
index /= 2;
}
}
int heap_pop(vector<int>& heap) {
int v = heap[1];
int n = heap[0];
swap(heap[1], heap[n]);
heap[0]--;
top_down(heap, 1);
return v;
}
int findKthLargest(vector<int>& nums, int k) {
vector<int> heap(k + 1, 0);
// build initial heap;
int index = 0;
while (index < nums.size() && index < k)
heap_push(heap, nums[index++]);
while (index < nums.size()) {
if (nums[index] > heap[1]) {
heap_pop(heap);
heap_push(heap, nums[index]);
}
index++;
}
return heap[1];
}
};
O(n*logk)
O(logk)
堆
Python3 Code
import heapq
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
size = len(nums)
h = []
for index in range(k):
# heapq 默认就是小顶堆
heapq.heappush(h, nums[index])
for index in range(k, size):
if nums[index] > h[0]:
heapq.heapreplace(h, nums[index])
return h[0]
复杂度
var findKthLargest = function(nums, k) {
nums.sort((a, b) => b - a).slice(0, k);
return nums[k-1]
};
215. 数组中的第 K 个最大元素
入选理由
暂无
题目地址
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
前置知识
题目描述
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4 说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。