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

19 篇文章 0 订阅
16 篇文章 0 订阅

问题:给定一个数组,对于某个区间,找出其中第 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 是等价单位
所以进行一些比较以及运算的时候,需要注意一下。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值