1. 排序法
对数组降序排列,然后取第k个元素
时间复杂度:
O
(
N
log
N
)
O(N\log N)
O(NlogN)
空间复杂度:
O
(
1
)
O(1)
O(1)
int findKthLargest(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),greater<int>());
return nums[k-1];
}
2. 堆
思路是创建一个小顶堆,将所有数组中的元素加入堆中,并保持堆的大小等于 k。这样,堆中就保留了前 k 个最大的元素。这样,最后堆顶的元素就是正确答案。
向大小为 k 的堆中添加元素的时间复杂度为 O ( log k ) O(\log k) O(logk) ,我们将重复该操作 N 次,故总时间复杂度为 O ( N log k ) O(N\log k) O(Nlogk),空间复杂度为 O ( N ) O(N) O(N)
在 Python 的 heapq 库中有一个 nlargest 方法,具有同样的时间复杂度,能将代码简化到只有一行。
python实现
class Solution:
def findKthLargest(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: int
"""
return heapq.nlargest(k, nums)[-1]
C++实现
int findKthLargest(vector<int>& nums, int k) {
//默认是大顶堆,greater<int>表明是小顶堆
priority_queue<int,vector<int>,greater<int>> minHeap;
for(int num:nums){
minHeap.push(num);
if(minHeap.size()>k) minHeap.pop();
}
return minHeap.top();
}
3.快速选择法
基于快速排序
时间复杂度:平均情况
O
(
N
)
O(N)
O(N) 最坏
O
(
N
2
)
O(N^2)
O(N2)
空间复杂度:
O
(
1
)
O(1)
O(1)
class solution{
public:
vector<int> nums;
int findKthLargest(vector<int>& nums, int k) {
this->nums=nums;
int n=nums.size();
//第k个最大对应第n-k+1个最小(对应位置的index是n-k,这里的对应位置指左边的都比它小,右边的都比它大)
return quickselect(0,n-1,n-k);
}
int quickselect(int left,int right,int target_index){
if(left==right) return nums[left];
int pivot_index=left+rand()%(right-left+1); //先随机生成枢纽元
pivot_index=partition(left,right,pivot_index); //再通过partition将枢纽元放到其该在的位置(即小于枢纽元的都在其左,大于枢纽元的都在其右)
if(pivot_index==target_index) return nums[pivot_index];
else if(pivot_index>target_index) return quickselect(left,pivot_index-1,target_index);
return quickselect(pivot_index+1,right,target_index);
}
int partition(int left,int right,int pivot_index){
swap(nums[pivot_index],nums[right]);
int store_index=left;
for(int i=left;i<=right;i++){
if(nums[i]<nums[right]) {
swap(nums[store_index],nums[i]);
store_index++; //这两行很精髓
}
}
swap(nums[store_index],nums[right]);
return store_index;
}
};