BFPRT算法
要解决的问题
在一个无序数组中,找到第k小的数.
一般做法是将数据加入一个小根堆中,依次弹出k个数.其时间复杂度为O(N*lgN).
BFPRT算法
要求空间复杂度O(1),时间复杂度O(N).
一种O(N)算法
算法步骤
- 先找到一个数作为
参照数
,对其进行荷兰国旗问题
的划分: 将小于参照数
的放在左边,大于参照数
的放在右边,等于参照数
的放在中间. - 判断所求的
第k位
在哪个区域:- 若所求的
第k位
位于等于区域
,则直接返回 - 若所求的
第k位
位于小于区域
,则对小于区域
进行第一步中荷兰国旗问题
的划分 - 若所求的
第k位
位于等于区域
,则对大于区域
进行第一步中荷兰国旗问题
的划分
- 若所求的
算法缺点:
若每次选择的参照数
都是划分区域内的最大或最小值,则算法的时间复杂度退化为O(N2).
因此我们期望所选取的参照数
要尽量位于划分区域的的中位数
附近. BFPRT算法
解决了这个问题.
BFPRT算法
算法步骤:
与上一个算法不同,BFPRT
算法选择参照数
的策略并不是随机的,这个策略正是BFPRT
算法的精髓所在.
其目的是要使所选择的参照数
接近数组的中位数. 其步骤如下:
- 先将数组中所有数相邻五个一组进行分组
- 找到所有小组中的中位数取出,组成一个新数组
- 对新数组重复步骤1,直到数组中只剩下一个数,取这个数作为
参照数
证明:
为什么要进行这么一个奇特的方法来选择参照数
?
因为我们所选取的数字是上一个数组中的中位数,这保证了总体上有接近一半的数字比我们所选取的参照数
小,也有接近一半的数字比我们所选取的参照数
大.