寻找无序数组中第k大数

本文探讨了sort函数的底层实现,包括内省式排序的原理——结合快速排序和堆排序,当数组长度小于16时使用插入排序。此外,还介绍了优先队列在寻找数组中第k大数问题上的应用,强调了理解排序算法和数据结构对优化问题解决的重要性。
摘要由CSDN通过智能技术生成


其实看到这个问题,作为一名力扣选手,我最先肯定想到sort,然后遍历即可,但是这个时候问题来了,sort的底层到底是什么,这个问题可能我们只是经常使用却很少关注。

下面我首先简单介绍一下sort的底层到底是什么?

浅谈sort函数底层:

        sort函数的底层用到的是内省式排序以及插入排序,那么什么是内省式排序呢?和插入排序又是如何组合的呢?

        根据维基百科描述:内省排序(英语:Introsort)是由David Musser在1997年设计的排序算法。这个排序算法首先从快速排序开始,当递归深度超过一定深度(深度为排序元素数量的对数值)后转为堆排序。

        那么我们再来回顾一下以上提到的3中排序方法:

       1.  快速排序:先选一个基准值(一般为首值),将比它大的数置于其右侧,将比它小的数置于它左侧,那么这个基准值所在的位置定是整个数组的有序位。然后递归该基准左右两子数组。算法复杂度为nlogn;
        2. 堆排序:将数组建立成大顶堆,重复从堆顶取出数值最大的结点(把根结点和最后一个结点交换,把交换后的最后一个结点移出堆,移出的这个数值为未排序数组的最后),并让残余的堆维持大顶堆的性质。时间复杂度为nlogn;
        3. 插入排序:对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。时间复杂度为n2;


其中先讲下快排和堆排,快排的平均复杂度为nlogn,但是它的复杂度是根据基准值来决定的,基准值选择的不好,最坏的复杂度会达到n2,而堆排序的复杂度是一定的为nlogn,那为什么不直接使用堆排序呢,是因为在将堆顶值与最后一个结点值交换并移除最后一个值后,在重新建堆的过程中,交换到堆顶的值显然比每个结点要小,但还是要经过对比判断,这个判断其实是多余的,因此这是它相比快排较慢的原因。

        于是,内省式排序结合了快排和堆排的特点,当快速排序大于一定深度(2logn)时,采用堆排序,以维持nlogn的复杂度。

        在sort函数中,内省排序过程中子数组长度小于16时,采用的是插入排序,为什么呢?因为当数组长度较短时,就是数组已经大致排序过了,对大致有序的数组(即逆序对不多了)用插入排序的算法复杂度会很小,可以想象成理牌的过程。

        在了解了sort的底层之后我们对于无序数组中的第k大数也有了充分的理解,现在我们再回到这个问题是否有了不一样的体会。

        现在我们对于这个问题的理解已经进入了下一层,我们使用sort也学会了分析数据大小对应排序算法的选择,当然这里我还介绍一种算法中也会经常用到的数据结构:优先队列。

        对于优先队列,其实就是一个队列,同时该数组中维护了一个大顶堆(或者小顶堆)的性质,在队列的操作中,始终维护着该性质,以如下例题为例,更方便我们理解:

剑指 Offer II 076. 数组中的第 k 大的数字 - 力扣(Leetcode)

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        priority_queue<int,vector<int>,greater<int>>que;//小根堆存储大元素
        for(int i=0;i<nums.size();i++){
            que.push(nums[i]);
            if(que.size()>k){
                que.pop();
            }
        }
        return que.top();
    }
};
        相信到这里大家对于排序也有了更深的理解,同时对于我们开头的问题也不在是简单的脱口而出sort即可,而是遇到问题会思考他的原理是什么,我该如何的设计sort才能更加优化排序算法。这些基于sort的思考希望能帮助到大家。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值