给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
这里说三个方法,再讲讲三种方法的优劣
第一种:排序
排序的思想很简单,降序排序,然后返回第k个数即可。
代码如下:
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),greater<int>());
return nums[k-1];
}
};
时间复杂度:O(N*logN)
空间复杂度:O(1)
第二种:大堆
由于大堆pop的顺序是降序的,pop k-1个数据,然后返回堆顶的数据即可。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> pq;
//建堆
for(const auto& e:nums)
{
pq.push(e);
}
//pop前k-1个数据
for(int i = 0;i<k-1;i++)
{
pq.pop();
}
//现在堆顶的数据就是第K大的数据了
return pq.top();
}
};
建堆的时间复杂度是O(N)
pop由于要向上调整,复杂度是O(logN)
所以总的时间复杂度:O(N+(k-1) * logk)
空间复杂度:O(N)
第三种:小堆
建一个大小为K的小堆。每当后面的数据大于小堆最小的数据,就把最小的数据给替换成当前数据。最后返回堆顶的数据。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
//建一个大小为K的小堆
priority_queue<int,vector<int>,greater<int>> pq(nums.begin(),nums.begin()+k);
//不断插入比自己最小的数据大的数据
for(size_t i = k;i<nums.size();i++)
{
if(pq.top()<nums[i])
{
pq.pop();
pq.push(nums[i]);
}
}
return pq.top();
}
};
时间复杂度:O(N+(N-k)*logN)
空间复杂度O(K)
综合来看:第三种是最好的,时间复杂度和第二种差不多,但空间复杂度很小。如果是在10亿里面找第100大的数据,第三种方法最适合。