顺序统计学总结
先来看一个问题:“给定一个无序的序列,求序列的中位数。”
正常的答案都是“先排序,再取A[n/2],花费O(nlgn)”,学习完本文后,发现其实能够在O(n)求出中位数。
但是要注意,有些场景下前一种方法更好,比如说:“要分别求第1个顺序统计量、第二个顺序统计量、第三个顺序统计量、....、第n个顺序统计量”,如果使用“先排序后取”的方法只要 O (nlgn),但是后一种方法,则要O(n^2)(n次select方法)。
顺序统计学要解决的问题是:“给定一个无序序列,问第k个小的数是什么?”
顺序统计学的算法是基于快速排序的partition函数,并运用了分治法的思想。
第i个顺序统计量:第i个最小的值。
本文将结合一些习题以便更好地讲解本主题。
伪代码:
最坏情况运行时间: O (n^2)
最好情况运行时间: O (1)
期望运行时间: O (n)
算法导论9.2-1中问:“对于上面的randomized_select,一定不会出现长度为0的递归调用”,因为在randomized_select中,我们的目的要求出第i个顺序统计量,因为调用randomized(A,a,b,i),的条件是A[a,...,b]之间一定有第i个顺序统计量,因此如果调用了长度为0的数组,则与条件矛盾。
接下来要证明为什么期望运行时间是 O (n)。
(下述证明需要假设所有元素都是不相同的)
设随机变量T(n)表示select算法的运行时间,E(T(n))表示select算法的期望运行时间。
我们假设按照最坏情况来讨论,即如果划分了两个子数组后,都调用较长的那个子数组。
T(n)所有的情况如下图所示:
通过替换法即可证明E(T(n))=O(n)
而上面导致最坏情况出现的原因是randomized_partition的不确定性,怎么样能够得到一个好的划分呢?
Blum、Floyd、Pratt、Rivest、Tarjan发现了一个最坏情况还是线性时间的选择算法。
这个算法的基本思想是:每次找到的都是一个好的划分,这样就能保证select的时间是O(n)。具体细节可以看算法导论9.3节,这里我要提一些书上没有的:
(1)书上说的“分组,每组5个元素”,此处每组5个元素是最低要求,即只要大于等于5都可以,但是如果每组4个元素,则划分就不是一个好划分。
算法导论9.3-1中就需要证明如果每组3个元素,select就不是线性时间的了。
总结一句话:其实这个算法我们只要把他当做一个封装的子程序来用就可以了:“select(A,p,q,i)方法一定能够在线性时间找出A[p...q]中第i个小的元素。”
百度面试题:假设一整型数组存在若干正数和负数,现在通过某种算法使得该数组的所有负数在正数的左边,且保证负数和正数间元素相对位置不变。时空复杂度要求分别为:O(n)和O(1)
补充:综合编程 , 其他综合 ,