选择问题:一个含有n个不相等实数的集合,输出集合中的第i小元素
如果i=1,则为寻找最小元素
如果i=n,则为寻找最大元素
如果i处在集合序列的中间,则为寻找中位数
选最大
算法:顺序比较,首先假定第一个元素为最大,接着最大元素与第二个元素比较,若最大元素小于第二个元素,则两者交换,否则继续与第三个元素比较
最多需要做n-1次比较运算
最坏情况下时间复杂度:W(n)= n-1
选最大最小
同时求最大元素与最小元素
通常算法
- 先选最大元素
- 再在剩下的元素中选最小元素(与选最大类似)
时间复杂度:W(n) = n-1 + n -2 = 2n-3
分组算法
- 将n个元素两两一组,分成n/2组(假设n为偶数)
- 每组中的两个元素比较,分成较大的跟较小的,所有较大的元素放到一组,较小的元素放到一组,这样就得到n/2个较大元素与n/2个较小元素
- 在较大的元素中寻找最大元素
- 在较小的元素中寻找最小元素
时间复杂度:将元素分成较大一组与较小一组一共需要做n/2次比较,在较大元素中寻找最大元素需要做n/2 - 1次比较,寻找最小同理也需要n/2 - 1次比较
所以一共需要:W(n) = 3n/2 - 2
分治算法
- 将数组从中间划分成两个数组L1与L2
- 递归地在L1中寻找最大max1与min1
- 递归地在L2中寻找最大max2与min2
- max{max1,max2},min{min1,min2}
时间复杂度:W(n) = 2W(n/2) + 2, W(2) = 1
W(n) = 3n/2 -2
选第k小元素
方法1
做k次选最小的算法,时间复杂度W(n) = O(kn)
方法2
先排序然后再输出第k小元素
时间复杂度:O(nlogn)
方法3(分治)
- 用某个元素m,将数组S分为小于m的部分S1,与大于m的部分S2
- 如果S1中的元素个数n1>k,则就在S1中寻找第k小的元素,
- 如果n1 + 1 == k,则m就是第k小的元素
- 如果(n1 + 1)< k,则就在S2(元素个数n2)中寻找第(k-n1-1)小的元素
但是算法的效率取决于子问题的规模,如何通过m来控制子问题的规模?
- 可以将数组S分组,比如5个数一组,分成n/5组,每组由大到小排序,中位数放到一个集合M中,取集合M中的中位数作为m来控制子问题规模