算法_02_BFPRT

问题:

求一个数组中第 k 小的数。
要求:时间复杂度 严格O(N)

分析:
如果把数组进行排序,然后取出第 k 个数,那么复杂度为 O(NlogN)
这种方法不行。
那么下面给出两种解答方法,第二种就是今天讲的 BFPRT。

  1. 经典解法

    • 利用快排 patition 划分
    • 然后把比划分值小的放在左边,等于放中间,大于放右边,如果 k 在等于里面,那么命中了,如果没命中,重新划分,循环……

这种解法的缺点是什么呢,在于划分值得选取。所以 BFPRT 方法与经典解法的不同之处就在于划分值得选取。

  1. BFPRT

思路:

选择中位数组中的上中位数作为划分值。

具体实现:

  • 假设整个实现为函数 int f(int[] arr, int k),返回值即为最后答案
  • 先划分5个值为一组,每一组组内排序,每组内排序为常数级别,复杂度 O(1),有 N/5组,故,总的复杂度 O(N)
  • 选择每一组中的上中位数,组成新的数组 newArr,数组长度为 N/5
  • 调用自己,int m = f(newArr, N/10),即找到中位数组中的中位值m,这个值即为划分值。

下面分析为啥是这样的,看手写笔记吧:
长度为 N/5的 newArr 中,至少有 N/10的数比 m 小,
纵观所有数字,每5个一小组中,至少有两个数字比当初选择组成newArr 的那个值要小,那么这个数组中至少有3N/10个数字比 m 小,至多有7N/10个数字比 m 大。
同理,至少有3N/10个数字比 m 大,至多有7N/10个数字比 m 小。

也就是选择 m 作为划分值导致的结果是:比 m 大的和比 m 小的数都控制在3N/10~7N/10的范围内。
后续,要么对左边进行寻找,要么在右边进行寻找,那么就保证了,这种算法每次至少淘汰了3N/10个数字。

下面是潦草的笔记:

这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值