算法导论 — 7.3 快速排序的随机化版本

笔记

7.2节提到,快速排序的平均情况时间复杂度为 Θ ( n l g n ) Θ(n{\rm lg}n) 。然而实际应用中,输入数据有可能并不是完全随机排列的。比如,练习7.2-4描述的应用,需要排序的绝大多数输入数组都已经是基本有序的,在这种应用中,快速排序的效率总是十分低下。
  为了避免在某些应用中,由于输入数据并不是完全随机排列的,它们可能具备或大致上具备某种规律性,从而导致快速排序总是效率低下,可以通过在算法中引入随机性,使得快速排序算法在这些应用中也能得到较好的期望性能。即每次调用PARTITION(A, p, r)时,随机选择一个元素作为划分主元,而不是固定选择 A [ r ] A[r]
  在这里插入图片描述
  对于上文提到的输入数组总是基本有序的情况,随机化版本的快速排序算法也可以得到较好的平均时间复杂度。

练习

7.3-1 为什么我们分析随机化算法的期望运行时间,而不是其最坏运行时间呢?
  
  对于相同的输入,随机化算法每次运行的时间都各不相同。因此即使对于相同的输入,我们也可以认为算法的运行时间是一个随机变量。而对于一个随机变量,我们通常关注它的期望值。
  我们根本无法预测随机化算法在什么时候会出现最坏情况运行时间,因此分析最坏运时间意义不大。

7.3-2 在RANDOMIZED-QUICKSORT的运行过程中,在最坏情况下,随机数生成器RANDOM被调用了多少次?在最好情况下呢?以 Θ Θ 符号的形式给出你的答案。
  
  在RANDOMIZED-QUICKSORT的最坏情况下,对于一个包含 n n 个元素的数组,划分得到的两个子数组的大小分别为 n 1 n-1 0 0 。其中,大小为 n 1 n-1 的子数组会进一步划分。因此,划分过程一共被调用了 n 1 n-1 次,那么随机数生成器也一共被调用了 n 1 n-1 次,即 Θ ( n ) Θ(n)
  在RANDOMIZED-QUICKSORT的最好情况下,每次划分都是完全平衡的划分,即划分得到的 2 2 个子数组的规模分别为 ( n 1 ) / 2 ⌊(n-1)/2⌋ ( n 1 ) / 2 ⌈(n-1)/2⌉ 。于是可以得到调用划分过程的次数,也即调用随机数生成器的次数的递归式为
  在这里插入图片描述
  有经验的读者应该一眼能看出这个递归不等式的解为 T ( n ) = Ω ( n ) T(n) = Ω(n) 。如果要严格证明,我们需要用代入法去验证这个递归不等式。应用代入法时应当假设 T ( n ) c n d T(n) ≥ cn-d ,其中 c > 0 c > 0 并且 d > 0 d > 0
  我们先考察初始情况,初始情况为 n = 0 n = 0 n = 1 n = 1 。当 n = 0 n = 0 时,有 T ( 0 ) = 0 T(0) = 0 ,即空的子数组是不需要进行划分的。根据我们对 T ( n ) T(n) 的假设,有 T ( 0 ) = 0 d T(0) = 0 ≥ -d ,这个不等式显而易见是成立的 (因为我们已经假设了 d > 0 d > 0 )。
  当 n = 1 n = 1 时,有 T ( 1 ) = 0 T(1) = 0 ,即单个元素的子数组也是不需要进行划分的。根据我们对 T ( n ) T(n) 的假设,有 T ( 1 ) = 0 c d T(1) = 0 ≥ c-d ,显然当 d c d ≥ c 时,这个不等式是成立的。即只要满足不等式 d c {\color {red} d ≥ c} ,那么 T ( n ) c n d T(n) ≥ cn-d n = 1 n = 1 一定成立。
  下面进入数学归纳过程。假设 T ( n ) c n d T(n) ≥ cn-d 0 , 1 , , n 1 0, 1, …, n-1 都成立。于是有
  在这里插入图片描述
  为了让 T ( n ) c n d T(n) ≥ cn-d 成立,我们令 c n 2 c 2 d + 1 c n d cn-2c-2d+1≥cn-d ,可以得到 d 1 2 c d ≤ 1-2c 。这说明只要满足不等式 d 1 2 c {\color {red} d ≤ 1-2c} ,就可以使得 T ( n ) c n d T(n) ≥ cn-d 成立。
  综合初始情况和归纳过程,可以得到只要满足不等式 0 < c d 1 2 c {\color {red} 0 < c ≤ d ≤ 1-2c} ,就可以使得 T ( n ) c n d T(n) ≥ cn-d 对所有 n n 的取值都成立。比如我们可以取 c = 1 / 3 c = 1/3 并且 d = 1 / 3 d = 1/3 ,此时不等式 0 < c d 1 2 c 0 < c ≤ d ≤ 1-2c 是成立的,于是可以断言
  在这里插入图片描述
  以上只得到了 T ( n ) T(n) 的下限。而 T ( n ) T(n) 的上限是显而易见的,即 T ( n ) n T(n) ≤ n ,因为数组一共有 n n 个元素,每个元素至多被选为划分主元一次。综上所述, T ( n ) = Θ ( n ) T(n) = Θ(n) 。即在RANDOMIZED-QUICKSORT的最好情况下,随机数生成器被调用的次数也为 Θ ( n ) Θ(n)
  这里再多提一下,为什么初始情况要考察 n = 0 n = 0 n = 1 n = 1 两项?首先我们要证明的不等式 T ( n ) c n d T(n) ≥ cn-d n n 的取值范围是 n 0 n ≥ 0 ,因此初始情况必须包含 n = 0 n = 0 。而递归不等式 T ( n ) 2 T ( ( n 1 ) / 2 ) + 1 T(n)≥2T(⌊(n-1)/2⌋)+1 n n 的取值范围是 n 2 n ≥ 2 ,因为将 n = 1 n = 1 代入这个不等式得到 T ( 1 ) 2 T ( 0 ) + 1 = 1 T(1) ≥ 2T(0) + 1 = 1 ,这显然是不成立的 (因为 T ( 1 ) T(1) 等于 0 0 )。所以进入数学归纳过程必须将 n = 1 n = 1 排除在外,而应当从 n = 2 n = 2 开始归纳,故 n = 1 n = 1 就被列入初始情况。

猜你喜欢

转载自blog.csdn.net/yangtzhou/article/details/85231949