leetcode 215. 数组中的第K个最大元素 medium
题目描述:
解题思路:
方法一: 快速选择 (时间复杂度 O(n)空间复杂度O(1))
方法二: 求第k个最大, 用最小堆 (时间复杂度 O(nlogk), 空间O(k))
代码:
go 三向切分版
官方更新了用例 用三向切分能过, 单向扫描会超时
func findKthLargest(nums []int, k int) int {
n := len(nums)
if k <=0 || n < k {
return -1
}
target := n - k
l, r := 0, n-1
el, er := partition(nums, l, r)
for target < el || target > er {
if target < el {
r = el - 1
} else {
l = er + 1
}
el, er = partition(nums, l, r)
}
return nums[el]
}
func partition(nums []int, l, r int) (int, int) {
random := rand.Intn(r-l+1)+l
nums[l], nums[random] = nums[random], nums[l]
less, more := l, r+1
pivot := nums[l]
cur := l + 1
for cur < more {
if nums[cur] < pivot {
less++
nums[cur], nums[less] = nums[less], nums[cur]
cur++
} else if nums[cur] > pivot {
more--
nums[cur], nums[more] = nums[more], nums[cur]
} else {
cur++
}
}
nums[l], nums[less] = nums[less], nums[l]
return less, more - 1
}
// 快速选择
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
if (k <= 0 || nums.size() < k)
return -1;
k = nums.size() - k; // 转为下标
int l = 0, r = nums.size()-1;
int idx = partition(nums, l, r);
while (idx != k){
if (k<idx)
r = idx-1;
else
l = idx + 1;
idx = partition(nums, l, r);
}
return nums[idx];
}
int partition(vector<int> &nums, int l, int r){
// 随机选择作为主元的那个元素
int rand_idx = rand() % (r-l+1) + l;
swap(nums[l], nums[rand_idx]);
int less = l, pivot = nums[l];
for (int i = l + 1; i <= r; i++){
if (nums[i] < pivot)
swap(nums[i], nums[++less]);
}
swap(nums[l], nums[less]);
return less;
}
};
// 小顶堆
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int, vector<int>, greater<int>> pq;
for (int num: nums){
if (pq.size() < k)
pq.push(num);
else if (pq.top() < num){
pq.pop();
pq.push(num);
}
}
return pq.top();
}
};