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 如果每次划分都分成区间长度为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)。

你可能感兴趣的:(Leetcode每日一题打卡)