leetcode215---Kth Largest Element in an Array(第k大元素)

问题描述:

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.

问题求解:

方法一:利用快排的思想,使用快速选择算法(QuickSelect),时间复杂度为O(N).

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int n=nums.size();
        vector<int> left;
        vector<int> right;
        int key=nums[0];//(1)将nums[0]设置为主元,以此划分左右两部分
        for(int i=1;i<n;i++)
        {
            if(nums[i] > key)
            {//(2)大于key的放右边
                right.push_back(nums[i]);
            }
            else if(nums[i] < key)
            {//(3)小于key的放左边
                left.push_back(nums[i]);
            }
        }
        int nr=right.size();
        int nl=left.size();
        if(k <= nr)
        {//(4)k<=nr则直接在右边找
            return findKthLargest(right, k);
        }
        if(k > n-nl)
        {//(5)k>n-nl则需在左边找k-(n-nl)个
            return findKthLargest(left, k-(n-nl));
        }
        return key;//(6)主元即是第k大
    }
};

进一步,优化空间复杂度到O(1),代码如下:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        int L = 0, R = nums.size() - 1;
        while (L < R) {
            int left = L, right = R;
            int key = nums[left];//(1)主元
            while (left < right) {
                //(2)将大于key的放左边
                while (left < right && nums[right] < key) --right;
                nums[left] = nums[right];
                //(3)将小于key的放右边
                while (left < right && nums[left] >= key) ++left;
                nums[right] = nums[left];
            }
            nums[left] = key;
            if (left == k - 1) return nums[k - 1];
            else if (left > k - 1) R = left - 1;//(4)更新R
            else L = left + 1;//(5)更新L
        }
        return nums[k - 1];
    }
};

方法二:先排序再选择。时间复杂度:O(N*logN),空间复杂度:O(1)。

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());//(1)排序
        return nums[nums.size() - k];//(2)找到第k大元素
    }
};

方法三:建立大顶堆。make_heap()默认生成的是大顶堆,该函数接受两个随机迭代器,分别表示first,end,区间范围。也可通过自定义的cmp来生成小顶堆。

pop_heap() 首元素和末元素交换,再重新堆排序。 
pop_back() 删除容器中最后一个元素。

代码:

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        make_heap(nums.begin(), nums.end());//(1)生成大顶堆
        for(int i=0; i<k-1;i++) 
        {//弹出k-1个
            //(2)把堆顶元素取出来,放到数组或者是vector的末尾,用原来末尾元素去替代
            //然后end迭代器减1,执行siftdown()下溯函数来重新调整堆序。
            //执行完毕后,最大的元素并没有被取走,而是放于底层容器的末尾。
            pop_heap(nums.begin(), nums.end());
            //(3)若要取走,可使用pop_back()函数。
            nums.pop_back();
        }
        return nums.front();//(4)得到第k个大的
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值