【数据结构回顾】快速选择

问题:给定一个数组,对于某个区间,找出其中第 kkk 大的元素。

针对这个问题,有一个经典的算法被称为 快速选择算法,它可以在 O(n)\mathcal{O}(n)O(n) 的时间复杂度内找出区间内第 kkk 大元素。

还记得快速排序中的一个步骤——划分区间么?经过一个 O(n)\mathcal{O}(n)O(n) 复杂度的区间划分过程,可以将数组分为两部分,第一部分的元素值都小于等于 pivotpivotpivot,第二部分的元素值都大于等于 pivotpivotpivot

接下来,如果 pivotpivotpivot 新的下标 mid=k−1mid=k-1mid=k1,则直接返回 arrpivotarr_{pivot}arrpivot;否则,如果 k−1<midk-1<midk1<mid,则去左半部分区间继续查找第 kkk 大元素;否则,去右半部分区间继续查找第 k−mid−1k-mid-1kmid1 大元素。

ok

// 选择排序的partition
int partition(vector<int> &nums, int left, int right) {
   
    int p = nums[left], l = left, r = right;
    while(l < r) {
   
        while(l < r && nums[r] >= p) --r;
        nums[l] = nums[r];
        while(l < r && nums[l] <= p) ++l;
        nums[r] = nums[l];
    }
    nums[l] = p;
    return l;
}

int quick_select(vector<int> &nums, int left, int right, int k) {
   
    if(left == right) return nums[left];
    int p = partition(nums, left, right);
    if(p - left == k - 1) return nums[p];
    if(k - 1 < p - left) {
   
        return quick_select(nums, left, p - 1, k);
    }else {
   
        return quick_select(nums, p + 1, right, k - 1 - ( p - left ));
    }
}

需要注意的一点是 k - 1 与 p - left 是等价单位
所以进行一些比较以及运算的时候,需要注意一下。

全部评论

相关推荐

11-11 17:45
门头沟学院 Java
扶老蟑螂过马路被无证...:1. 技术栈那里把数据结构删了,小中厂用不上,大厂手撕能难死你,linux那里可以考虑删掉,还不如换个git团队协作开发 2.不要使用一些项目不匹配的技术,例如分库分表和你上边的ddd,真正使用ddd的都是【超】大规模,大部分都仍然使用多模块聚合mvc,这样虽然看起来高大上,但是新增了前期协定需求跟后期维护的成本,因为开发中都是选择最适合当起版本的开发方式跟中间件,这样反而会体现你为了学而学(因为可能面试官都不完全熟悉ddd,然后问你你也回答不出深度) 3.项目写了很多的redis使用,为什么技术栈不写上redis 4.项目技术栈跟业务需求高度重合,完全可以整合成一个,然后再去弄一个感兴趣的其他业务或者轮子,或者把上面的一个换下包装 5.奖项自己编一点奖学金,加个四六级,删掉蓝桥杯
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务