3种解法-求数组中的第k个最大的元素(选择问题)

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表明是小顶堆
	   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;
    }
};

你可能感兴趣的:(数据结构,算法,leetcode,快速排序)