[Leetcode] 215. Kth Largest Element in an Array 解题报告

本文介绍两种高效算法来解决寻找未排序数组中的第K大元素的问题。一种基于堆排序,通过构建大顶堆并逐步移除堆顶元素找到目标值;另一种基于快速排序的思想,利用partition函数分治查找。

题目

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

思路

1、基于堆排序的方法:联想到堆排序的实现,我们可以在这里采用:首先将数组调整成为一个大顶推,然后依次往外取元素,取到的第k个元素即为第k大的。建堆的时间复杂度是O(n),每次pop_heap之后调整堆的时间复杂度是O(logn),所以总体时间复杂度是O(n+klogn),空间复杂度是O(1)(如果允许修改原数组的话,否则空间复杂度是O(n))。

2、基于快速排序的方法:在快速排序中有一个子函数叫做partition,负责将某个哨兵元素排到相应的位置,左边的位置上的值都比它小,而右边位置上的值都比它大。这个方法的理论复杂度是O(n)。具体到这道题目,我们使用分治每次将数组划分为两段,并且返回划分点的位置,如果这个位置恰好是我们要的第k大的数,那么返回这个数即可。否则如果返回的位置小于要找的位置,则向右边的一半数组继续寻找;如果返回的位置大于要找的位置,则向左边继续寻找。这种方法的空间复杂度是O(1),平均时间复杂度是O(nlogn),最大时间复杂度是O(n^2)。但是通常情况下,基于快速排序的方法的实际花费时间要小于理论值(和现代计算机体系结构有关)。

代码

1、基于堆排序的方法:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        make_heap(nums.begin(), nums.end());
        for(int i = 0; i < k - 1; ++i) {
            std::pop_heap(nums.begin(), nums.end());
            nums.pop_back();
        }
        return nums.front();
    }
};

2、基于快速排序的方法:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {  
        int len = nums.size(), left = 0, right = len-1, ans, pos = len-k;  
        while((ans=partition(nums, left, right)) != pos) { 
            ans<pos?left = ans + 1: right = ans - 1;  
        }
        return nums[len-k];  
    }  
private:
    int partition(vector<int>& nums, int left, int right) {  
        int val = nums[right];  
        for(int i = left; i < right; ++i) {  
            if(nums[i] < val) {
                swap(nums[left++], nums[i]);  
            }
        }
        swap(nums[right], nums[left]);  
        return left;  
    }  
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值