• 【C++、快速排序巧用】LeetCode215 数组中的第K个最大元素


    1. 数组中的第K个最大元素

    在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

    示例 1:

    输入: [3,2,1,5,6,4] 和 k = 2
    输出: 5
    

    示例 2:

    输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
    输出: 4
    

    说明:

    你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

    方法一

    采用快速排序的思想,随机选取一个值作为分割线,分割线左边的都不比这个值大,分割线右边都比这个值大。

    只需要比较分割线的索引值n-k的值(目标值)
    如果目标点正好等于分割点,说明此时的分割点正是要找的第K大的值;
    如果目标点在分割点右侧,说明左侧区间有待缩减掉,仅对右半边递归;
    如果目标点在分割点左侧,说明右侧区间有待缩减掉,仅对左半边递归。

    class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            return findKthLargest(nums, 0, nums.size()-1, k);
        }
    private:
        int findKthLargest(vector<int>& nums, int low, int high, int k){
            int n=nums.size();
            int index = partition(nums, low, high);
            if(index==n-k) return nums[index];
            else if(index < n-k) return findKthLargest(nums,index+1,high,k);
            else return findKthLargest(nums,low,index-1,k);
        }
    
        int partition(vector<int>& nums, int low, int high) {
            uniform_int_distribution<int> u(low, high);
            default_random_engine e;//生成无符号随机整数
            std::swap(nums[u(e)], nums[high]);//避免最糟糕的情况出现,随机选值放到最右端
            int i = 0, j = 0;
            for (i = low, j = low;j < high;++j) {//从头到尾遍历每个数,但不遍历最后的基准值
                if (nums[j] <= nums[high]) {//如果发现当前数不大于基准值
                    std::swap(nums[i++], nums[j]);//把这个不大于基准值的数与i位置上的数交换,同时i++
                }
            }//结束后,i之前的所有的数都不大于基准值,i之后所有的数都大于基准值;退出的时候j=high
            std::swap(nums[i], nums[j]);//把j位置的数(基准值)换到i位置上来
            return i;
        }
    };
    

    后续方法参考:https://blog.csdn.net/lv1224/article/details/80112229

    方法二(用STL的轮子nth_element())

    使用STL库函数 nth_element(),通过调用nth_element(start, start+n, end) 方法可以使第n大元素处于第n位置(从0开始,其位置是下标为 n的元素),并且比这个元素小的元素都排在这个元素之前,比这个元素大的元素都排在这个元素之后,但不能保证他们是有序的

    class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            nth_element(nums.begin(),nums.end()-k,nums.end());
            return *(nums.end()-k);
        }
    };
    

    方法三(用STL的轮子sort)

    直接排序,取值

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

    方法四

    利用 multiset 本身有序,维持 multiset 大小 K,则 multiset 首元素即为所求。
    注意: 由于数组本身存在重复元素,所以这里要用multiset。

    class Solution {
    public:
        int findKthLargest(vector<int>& nums, int k) {
            multiset<int> s;
            for(auto &m:nums){
                s.insert(m);
                if(s.size()>k) s.erase(s.begin());
            }
            return *s.begin();
        }
    };
    
  • 相关阅读:
    Visual GC(监控垃圾回收器)
    垃圾收集(GC)中如何确定哪些内存是"垃圾
    Java for循环和foreach循环的性能比较
    <mvc:annotation-driven />做了什么
    聊一聊分布式锁的设计
    String类对象的比较
    Java 中 Comparable 和 Comparator 比较
    系统对接API调用
    深入理解Java中的组合和继承
    面向对象设计七大原则
  • 原文地址:https://www.cnblogs.com/dindin1995/p/13059102.html
Copyright © 2020-2023  润新知