选择问题
- 输入:集合L (含n个不等的实数)
- 输出:L中第 i 小元素
- i=n,称为最大元素
- i=1,称为最小元素
- 位置处在中间的元素,称为中位元素
- n为奇数,中位数唯一,i= (n+1)/2
- n为偶数,可指定 i= n/2+1
选最大或最小
- 算法:顺序比较,依次比较序列中的所有数,保存每次比较的较大值或较小值。
- 时间复杂性:W(n-1)
同时选最大与最小
通常算法
- 顺序比较,先选最大max。
- 顺序比较,在剩余数组中选最小min,类似于选最大算法,但比较时保留较小的数。
时间复杂性:W(n) = n-1 + n-2 = 2n-3
分组算法
- 最坏情况时间复杂度3n/2-2
分治算法
- 将数组 L 从中间划分为两个子数组 L1 和 L2
- max = max { max1,max2 }
- min = min { min2,min2 }
- L1 和 L2 分别再分组,递归地在 L1 中求 max1 和 min1,递归地在 L2 中求 max2 和 min2
- 最坏情况时间复杂度 3n/2 -2
选第二大
输入:n 个数的数组 L
输出:第二大的数
通常算法:顺序比较
1.顺序比较找到最大max
2.从剩下n -1个数中找最大,就是第二大(再次调用找最大)
时间复杂度:W( n ) = n -1 + n - 2 = 2n - 3
提高效率的途径
- 成为第二大数的条件:仅在与最大数的比较中被淘汰。
- 要确定第二大数,必须知道最大数。
- 在确定最大数的过程中记录下被最大数直接淘汰的数。
- 在上述范围(被最大数直接淘汰的数)内的最大数就是第二大数。
- 设计思想:用空间换时间
锦标赛算法
- 两两分组比较,大者进入下一轮,直到剩下 1 个元素 max 为止。
- 在每次比较中淘汰较小元素,将被淘汰元素记录在淘汰它的元素的链表上。
- 检查 max 的链表,从中找到最大元,即第二大。
- 实例:
- 时间复杂度分析
第一阶段:元素数为n,比较次数为n-1,淘汰了n-1个元素
第二阶段:元素数为logn比较次数为logn-1淘汰元素数为logn-1
时间复杂度是W(n) = n - 1 + logn - 1 = n + logn - 2
一般性选择问题
- 问题:选第 k 小。
- 输入:数组 S,S 的长度 n,正整数 k,1<=k<=n。
- 输出:第 k 小的数。
简单算法
- 调用k次选最小算法,时间复杂度为 O (k n) 。
- 先排序,然后输出第 k 小的数,时间复杂度为 O(n logn)。
分治算法
假设元素彼此不相等
设计思想:
- 用某个元素 m* 作为标准将 S 划分成 S1 与 S2,其中 S1 的元素小于 m*,S2 的元素大于等于 m*。
- 如果 k <= |S1|,则在 S1 中找第 k 小;如果 k = |S1| + 1,则 m* 是第 k 小,如果 k > |S1| + 1,则在 S2 中找第 k - |S1| - 1小。
- 算法效率取决于子问题规模,如何通过 m* 控制子问题规模?
将所有数分组并在组内排序,找到每组的中位数的中位数,就是 m* 的值。
实例中,B 中数据比 m* 大,C 中数据比 m* 小,A、D中的数据无法判断,即 8,7,10,4 需要与 9 比较。 - 归约为子问题,递归实现。
选择问题的算法分析
算法的时间复杂度:W(n)=O(nlogn)
扫描二维码关注公众号,回复:
9529503 查看本文章
递归调用
- 求 m* 的工作量与 |M| = n / t 相关,t 为每组元素数,t大,|M| 小。
- 归约后子问题大小与分组元素数 t 有关,t 大,子问题规模大。
- |M| 与归约后子问题规模之和小于 n,递归树每行的工作量构成公比小于 1 的等比级数,算法复杂度是 O(n)。