Leetcode每日一题打卡

215.数组中的第K个最大值

原题
分治算法
第一反应,先排序,再倒着遍历,暴力直接找到最大值,时间复杂度O(nlogn)。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        sort(nums.begin(),nums.end());
        int index=nums.size()-1;
        while(k>1) {
            index--;
            k--;
        }
        return nums[index];
    }
};

咦????竟然没有超时……
官答有两种解答方法:
方法一:快速选择算法
根据快速排序算法加以改动:已知快排每次划分后确定一个元素的正确位置,那么根据题目来说,我们需要确定的是第nums.size()-k个位置的正确元素。使用递归的算法,每次确定区间(l, r)中q位置的元素,如果q==k,就返回该元素,如果q<k,就在区间(q+1, r)进行迭代,否则就在区间(l, q-1)进行迭代。
如果每次划分都分成区间长度为1和n-1的两个区间,那么时间复杂度会是O(n^2),为了避免这种情况,这里使用随机划分区间。

class Solution {
public:
    int selectQuick(vector<int>& nums, int l, int r, int k) {
        int q=randomPartition(nums, l, r);
        if(q==k) return nums[q];
        return q<k?selectQuick(nums, q+1, r, k):selectQuick(nums, l, q-1, k);
    }
    int randomPartition(vector<int>& nums, int l,int r) {
        int i=rand()%(r-l+1)+l;
        swap(nums[i], nums[r]);//将待定位元素放到最后
        return Partiton(nums, l, r);
    }
    int Partiton(vector<int>& nums, int l, int r) {
        int m=nums[r], index=l-1;
        for(int i=l;i<r;i++){
            if(nums[i]<=m){
                //将该元素的值放到左边
                swap(nums[++index],nums[i]);
            }
        }
        swap(nums[++index],nums[r]);//将数值m放在正确的位置:index上面
        return index;
    }
    int findKthLargest(vector<int>& nums, int k) {
        return selectQuick(nums, 0, nums.size()-1, nums.size()-k);
    }
};

这样时间复杂度是O(n),空间复杂度是O(logn)【递归使用栈的空间代价为O(logn)】
方法二:基于堆排序的选择方法
建立一个最大堆,后删除k-1次,就得到了目标值。

class Solution {
public:
    //利用数组构造堆
    void maxHeapify(vector<int>& nums, int i, int heapSize) {
        int l=2*i+1, r=2*i+2, largeset=i;
        if(l<heapSize&&nums[l]>nums[largeset]) largeset=l;
        if(r<heapSize&&nums[r]>nums[largeset]) largeset=r;
        if(largeset!=i) {
            swap(nums[largeset],nums[i]);
            maxHeapify(nums, largeset, heapSize);
        }
    }
    void buildHeap(vector<int>& nums, int heapSize) {
        for(int i=heapSize/2; i>=0;i--)
            maxHeapify(nums, i, heapSize);
    }
    int findKthLargest(vector<int>& nums, int k) {
        int heapSize=nums.size();
        buildHeap(nums, heapSize);
        for(int i=nums.size()-1;i>=nums.size()-k+1;i--){
            swap(nums[0],nums[i]);
            --heapSize;
            maxHeapify(nums, 0, heapSize);
        }
        return nums[0];
    }
};

时间复杂度是O(n+klogn)渐进于O(nlogn),空间复杂度:使用递归——O(logn)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值