第8.1节-排序算法的下界
Exercise 8.1-1
我们可以构造一个顶点集为索引的图,并在任意两个在最短路径上比较的索引之间放置一条边。我们需要这个图是连通的,否则我们可以运行两次算法,第一次是一个分量的所有元素都小于另一个分量,第二次是第二个分量的所有元素都大于另一个分量。只要我们保持每个组件中元素的相对顺序相同,算法就会采用完全相同的路径,从而产生相同的结果。这意味着输出中不会有任何差异,即使应该有。对于一个有n个顶点的图,众所周知,它至少需要n−1条边才能连通,因为增加一条边可以使连通分量的数量减少至少一个,而没有边的图有n个连通分量。所以它的深度至少是n - 1。
Exercise 8.1-2
由于lg(k)是单调递增的,我们使用公式A.11来近似求和:
![]()
由此我们得到不等式
![]()
也就是Θ(nlgn)。
Exercise 8.1-3
假设有一个矛盾,存在一个c1,使得对于每一个n≥k,至少一半长度为n的输入深度不超过
。然而,深度树的元素个数不超过
。然而
,只要
。这是一个矛盾。
为了让它们的1/n部分具有较小的深度,类似地,我们得到一个相反的表达式因为
, n足够大。
为了使一个算法对1/ 2^n的输入是线性的,我们又得到了一个矛盾,因为对于足够大的n。
这个故事的寓意是:n!生长得非常快。
Exercise 8.1-4
在本节中,我们假设需要构造一个二叉决策树来表示比较。因为每个子序列的长度是k,所以有
个可能的输出排列。为了计算决策树的高度h,我们必须有
。两边都取对数,利用练习2给出的结果
第8.2节-计数排序
Exercise 8.2-1
我们有C = <2 ,4 ,6 ,8 ,9 ,9 ,11>。然后,在第10-12行循环的连续迭代之后,我们有B = <,,,,, 2,,,,, >,B = <,,,,, 2,, 3,, ,>,B = <,,,, 1,, 2,, 3,,, >,最后,B = <0,0,1,1,2,2,3,3,4,6,6>
Exercise 8.2-2
假设i < j的位置i和j都包含某个元素k。我们考虑COUNTING-SORT的第10到12行,在这里我们构造输出数组。由于j > i,循环将在检查A[i]之前检查A[j]。当它这样做时,算法正确地将A[j]放置在b的m = C[k]的位置上。因为C[k]在第12行是递减的,并且再也不会增加,我们可以保证当for循环检查A[i]时,我们将得到C[k] < m。因此A[i]将被放置在输出数组的较早位置,证明了稳定性。
Exercise 8.2-3
算法仍然可以正常工作。从C中取出元素并放入B中的顺序不会影响具有相同键的元素的位置。它仍然会用k键的元素填充区间(C[k−1],C[k])。它是否稳定的问题并没有很好地表达。为了使稳定性有意义,我们需要对除了键之外还有其他信息的项进行排序,而所写的排序只适用于没有键的整数。我们可以考虑通过将A的元素放入数组C中每个单元格的元素集合来扩展该算法。然后,如果我们使用FIFO集合,对第10行的修改将使其稳定,如果我们使用LILO,它将是反稳定的。
Exercise 8.2-4
该算法将完全按照第1行到第9行的计数COUNTING-SORT进行预处理,以便C[i]包含数组中小于或等于i的元素的数量。当查询有多少个整数落入范围[a..b],只需计算C[b]−C[a−1]。这需要O(1)次,并产生期望的输出。
第8.3节-基数排序
Exercise 8.3-1
从左边未排序的单词开始,逐步按更重要的位置进行稳定排序。
Exercise 8.3-2
插入排序和归并排序是稳定的。堆排序和快速排序则不是。为了使任何排序算法稳定,我们可以进行预处理,用有序对替换数组中的每个元素。第一个条目将是元素的值,第二个值将是元素的索引。例如,数组[2,1,1,3,4,4,4]将变成[(2,1),(1,2),(1,3),(3,4),(4,5),(4,6),(4,7)]。我们现在解释(i, j) < (k, m)为,如果i < k或i = k 和 j < m。在小于的定义下,算法保证是稳定的,因为我们的每个新元素都是不同的,并且索引比较确保如果一个重复元素在原始数组中出现较晚,它在排序数组中必须出现较晚。这将使空间需求加倍,但运行时间将渐近不变。
Exercise 8.3-3
在对第i位数字进行排序之后,我们将证明,如果只限制最后i位数字,则列表是有序的。这对于i = 1来说是微不足道的,因为它只是表明我们刚刚排序的数字是有序的。现在,假设它对i - 1成立,我们对i也证明了这一点。假设有两个元素,当被限制在最后i位时,它们在第i步之后没有排序。然后,我们必须保证它们的第i位是相同的否则第i位的排序就会把它们放在正确的顺序上。由于它们具有相同的第一位数字,因此它们的相对顺序由它们对最后i - 1位的限制决定。然而,在第i - 1步中,它们的顺序是正确的。由于第i位的排序是稳定的,因此它们的相对顺序与前一步相同。这意味着它们的顺序仍然是正确的。我们使用稳定性来证明在排序之前保持正确的顺序。
Exercise 8.3-4
首先遍历整数列表并将每个整数转换为以n为基数,然后对它们进行基数排序。每个数字最多有
位数字,所以只需要3次传递。对于每次传递,有n个可能的值可以取,所以我们可以使用计数排序在O(n)时间内对每个数字进行排序。
Exercise 8.3-5
由于一次循环由第1 - 2行循环的一次迭代组成,因此只需要d次循环。因为每个数字都可以是10个十进制数中的一个,所以需要记录的堆数最多是10。
第8.4节-桶排序
Exercise 8.4-1
形成的子表为:<.13,.16>,<.20>,<.39>,<.42>,<.53>,<.64>,<.71,.79>,<.89>。把它们放在一起,我们得到<.13,.16,.20,.39,.42,.53,.64,.71,.79,.89>。
Exercise 8.4-2
在最坏的情况下,我们可能有一个包含数组所有n个值的桶。由于插入排序在最坏情况下的运行时间为O(n^2),因此Bucketsort也是如此。我们可以通过使用归并排序来对每个桶进行排序来避免这种情况,在最坏的情况下,它的运行时间为O(n*lgn)。
Exercise 8.4-3
X是0或2,各有1 / 4的概率,为1有1 / 2的概率。注意E[X] = 1,因此(E[X])^2 = 1。同样,X^2取0或4的概率各有1 / 4,为1的概率是1 / 2。因此,E[X^2] = 1.5。
Exercise 8.4-4
定义
和 ci = {(x, y)|
},对于i = 1,2,…n。ci区域将单位磁盘划分为n个等面积的部分,我们将其用作桶。由于点均匀分布在磁盘上,并且每个区域的面积相等,因此桶排序将在预期时间内运行Θ(n)。
Exercise 8.4-5
我们必须在桶排序中为桶选择边界这样从分布中抽取的元素出现在任意一个桶中的概率是近似相等的。要做到这一点,我们可以执行二分搜索来找到分母至少为n的常数分数的并进有理数。找到每一个只需要lg(n)时间。然后,这些就形成了桶排序的边界。在这些桶中的任何一个桶中都有一个期望的常量数量的元素,所以在这一点上可以使用任何您想要的排序。