# 练习题

## 8.1 排序算法时间的下界

8.1-1

n-1，因为一个有序数组的排序中最少会进行n-1次比较\</span>

8.1-2

数学题目不要看我

8.1-3

幸好有答案，不然题目的意思都看不懂。先解释一下题目的意思，高手跳过。\
对于一个组包含n个元素的数据，可以有n!种不同的排列，也就是有n!种不同的输入。\
对于一个排序算法，可以用一个决策树来表示。\
对于任意一种输入排列，从树顶出发，根据该内结点的提示作对应的比较和调整，并决定进入其左子树还是右子树。当这个排列成为一个有序序列时到达叶子结点。这个叶结点就是这个输入排列对应的叶结点。从根结点到叶结点的长度就是这个排列的比较次数。\
具有线性时间的输入是指n!种输入排列中满足以下条件的排列：排列的运行时间小于或等于O(n) 假设对于一组包含n个元素的数据，有n!种不同的输入排列，其中具有线性时间的输入排列有m种，求k = m/(n!)\
若k<=1/2，那么所证明的命题成立。\
后面一问是指k和1/n、1/(2^n)的比较

证明：\
这m种输入排列分别对应决策树中的m个叶结点。一棵高度为h的树最多有2^h个叶结点。\
2^h >= m =====> h >= lg(m)\
若要一棵决策树包含m个叶结点，这棵决策树的高度最少为lg(m)\
根据《算法导论》P98中定理8.1的公式，h>=O(nlgn)\
只需要证明lg(m) <= O(nlgn)，那么k就是可以取到的值。\
分别令k等于1/2、1/n、1/(2^n),代入m = k \* (n!)得：\
计算结果略，这几个值都不满足

8.1-4

不能简单地将子序列的下界合起来，这样做不准确。因为有可能存在一种比“独立解决各个子序列的排序”更快的算法。\
这种计算比较次数的一般思路是：\
(1)统计有多少种不同的输入排列\
(2)每一种输入排列对应决策树的一个叶子结点。\
(3)根据叶结点的数量与树的高度的关系，计算决策树的高度\
(4)从树根到叶结点的长度就是这个叶结点对应的输入排列的比较次数\
对于这道题，可以这样计算：\
(1)每个子序列有k个元素，因此有k!种不同的输入排列。\
共有n/k个子序列，因此共有(k!)^(n/k)种输入排列\
(2)决策树至少有(k!)^(n/k)个叶子\
(3)一棵高度为h的决策树，最多有2^h个叶子结点\
2^h >= (k!)^(n/k) =====> h >= (n/2)lg(k/2)\
(4)对于任意一树决策树，至少有一条叶子路径长度超过(n/2)lg(k/2)，因此比较次数下界是O(nlgk)

## 8.2 计数排序

8.2-1因为假设待排序数据的范围中\[0,k]，所以B被初始化为-1

```
    A = {6 0 2 0 1 3 4 6 1 3 2}
==> C = {2 2 2 2 1 0 2}
==> C = {2 4 6 8 9 9 11}
==> B = {-1 -1 -1 -1 -1 2 -1 -1 -1 -1 -1}
    C = {2 4 5 8 9 9 11}
==> B = {-1 -1 -1 -1 -1 2 -1 3 -1 0 -1 -1}
    C = {2 4 5 7 9 9 11}
==> B = {-1 -1 -1 1 -1 2 -1 3 -1 -1 -1}
    C = {2 3 5 7 9 9 11}
==> B = {-1 -1 -1 1 -1 2 -1 3 -1 -1 6}
    C = {2 3 5 7 9 9 10}
==> B = {-1 -1 -1 1 -1 2 -1 3 4 -1 6}
    C = {2 3 5 7 8 9 10}
==> B = {-1 -1 -1 1 -1 2 3 3 4 -1 6}
    C = {2 3 5 6 8 9 10}
==> B = {-1 -1 1 1 -1 2 3 3 4 -1 6}
    C = {2 2 5 6 8 9 10}
==> B = {-1 0 1 1 -1 2 3 3 4 -1 6}
         C = {1 2 5 6 8 9 10}
==> B = {-1 0 1 1 2 2 3 3 4 -1 6}
         C = {1 2 4 6 8 9 10}
==> B = {0 0 1 1 2 2 3 3 4 -1 6}
         C = {0 2 4 6 8 9 10}
==> B = {0 0 1 1 2 2 3 3 4 6 6}
         C = {0 2 4 6 8 9 9}
```

8.2-2

辅助数组C\[j]记录的是小于或等于i的元素的个数。若几个元素的大小相等，则把这些元素依次从后往前填入排序数组中。因为处理元素的顺序是从后往前的(L9)，所以晚出现的元素会填到后面。因此是稳定排序

8.2-3

不稳定

8.2-4

COUNTING-SORT(A, B, k)中步骤L1-L4求出C，ans(a, b) = C\[b] - C\[a-1], C\[-1]=0

## 8.3 基数排序

8.3-1

```
    A = {COW, DOG, SEA, RUG, ROW, MOB, BOX, TAB, BAR, EAR, TAR, DIG, BIG, TEA, NOW, FOX}
==> A = {SEA, TEA, MOB, TAB, DOG, RUG, DIG, BIG, BAR, EAR, TAR, COW, ROW, NOW, BOX, FOX}
==> A = {TAB, BAR, EAR, TAR, SEA, TEA, DIG, BIG, MOB, DOG, COW, ROW, NOW, BOX, FOX, RUB}
==> A = {BAR, BIG, BOX, COW, DIG, DOG, EAR, FOX, MOB, NOW, ROW, TAB, TAR, TEA, SEA, RUB}
```

8.3-2

稳定排序有：插入排序，合并排序\
方法：为每一个元素加入一个最初位置的属性，但两个元素的value一样大时，比较position，这样不会有相同的两个元素\
额外空间：O(4n)

8.3-3

(1)当d=1时，元素只有一位，对这一位做排序就相当于对整个数组做排序了。\
(2)证明当1到d-1位排序是正确的时，对d位的排序也是正确的。\
(3)对于数组中的任意两个数a和b，假设它们的第d位分别是ad和bd\
若adbd，则a会排到b的后面\
若ad=bd，则a和b的相对位置不变，因为是稳定排序，这一点可以保证。

8.3-5

最坏情况下需要d遍

## 8.4 桶排序

8.4-1

```
    A = ｛0.79， 0.13， 0.16， 0.64， 0.39， 0.20， 0.89， 0.53， 0.71， 0.42｝
==> A = ｛0.13， 0.16， 0.20， 0.39， 0.42， 0.53， 0.64， 0.79， 0.71， 0.89｝
==> A = ｛0.13， 0.16， 0.20， 0.39， 0.42， 0.53， 0.64， 0.71， 0.79， 0.89｝
```

8.4-2

最坏情况是O(n^2)\
修改：使用最坏情况下时间为O(nlgn)的算法来处理桶的插入操作

8.4-3

E(X^2)=1/4 *0 + 1/2* 1 + 1/4 *4 = 3/2*\
*E^2(X)=\[1/4* 0 + 1/2 *1 + 1/4* 2]^2 = 1^2 = 1

8.4-4

假设分为n个桶

```
BUCKET-SORT(A)  
1    n <- length[A]
2    for i <- 1 to n
3    do insert A[i] to list B[n*(A[i].x^2 + A[i].y^2)]
4    for i <- 0 to n-1
5        do sort list B[i] with insertion sort
6    concatenate the lists B[0], B[1], ……,B[n-1] together in order
```

8.4-5

不会，网上找了份答案，不懂\
X合适分布P，不必然是均匀分布，且不知局限。但P(x)值属于\[0,1]，且对于X严格单调递增，排序P(x)即排序X。将P(x)均匀分为n个项目组，因为X随机拔取，所以落入每个局限的概率雷同。 若是(i-1)/n <= p(xi) < i/n，则将它放入第i个桶中。
