习题6.1
1. hint
sort the list and then simply return the n/2th
elements of the sorted list.
效率:
假设排序算法的效率是O(nlogn),那么该算法的效率是O(nlogn)+Θ(1)= O(nlogn)
3.hint
a.
初始化C=A∩B=Φ
for every element
ai in A do
(1<=i<=n)
for every element bj in B
(1<=j<=m)
If ai=bj
add ai to C
delete bj from B
最差情况:C为空,比较的次数是nm.
b.方法一:
排序集合A
For every element
bj in B
用二分查找的办法在A中查找与bj相匹配的元素a
If 查找成功
Add a to C
效率分析:
假设排序的效率是O(nlogn),则该算法效率
O(nlogn)+mO(logn)=(n+m)O(logn)
方法二:
首先对A和B都分别排序.
然后对A和B应用合并排序,只输出它们的公有元素.
效率分析: 假设排序的效率是O(nlogn),则该算法效率
O(nlogn)+O(mlogm)+Θ(n+m)=O(slogs) where s=max{n,m}
方法三:
首先将A和B合并为L
排序L
从左至右成对扫描L
If Li=Li+1
Add Li to C
i←i+2
效率分析: 假设排序的效率是O(nlogn),则该算法效率
O((n+m)logn))+ Θ(n+m) =O(slogs) where s=max{n,m}
4.hint
a. 排序数组,然后返回它的第一和最后元素.
假设排序的效率是O(nlogn),则该算法效率O(nlogn)+Θ(1)+Θ(1)= O(nlogn)
b.蛮力和分治都是线性的,所以优于基于预排序的算法
习题6.3
2.b.
4.a.
5.a.
二叉查找树中最大值和最小值分别是树中最右边和最左边的结点.因此,从根开始,沿着向左的路径一直走到这样的结点:它的左孩子为空.这个结点里的值就是最小值.同理,可以找到最大值.最后,这两个值做一次减法运算即可.
算法的效率: Θ(logn)+ Θ(logn)+ Θ(1)= Θ(logn)
b.错误.
8.
不成立.
例如:列表{A,B},查找A,二分查找只做1次比较.而在2-3树中查找则要做2次比较
习题6.4
1.
a.
b.
c.
错误.对于列表{1,2,3}
按自顶向下:{3,1,2}
自底向上:{3,2,1}
5.a.设计一个算法,寻找并删除堆中最小元素,然后确定其时间效率
Hints: 最小元素一定在堆的叶子中.
在堆H[1..n]的后半部分,(H[ n/2
+1],…,H[n])中查找最小元素,并与最后的元素H[n]互换,删除最后的元素.堆规模降1,如果必要的话,调整元素H[n],使其满足双亲优势.
效率分析:
查找:Θ(n)
交换并删除: Θ(1)+ Θ(1)
调整为堆:O(logn)
b.设计一个算法,在给定的堆H中寻找并删除一个包含给定值v的元素,然后确定其时间效率.
Hints:
在H中顺序查找满足条件的第一个元素H[i].
H[i]与H[n]互换.
删除最后元素
堆规模降1
调整元素H[n]使其满足双亲优势
效率分析:
查找:Θ(n)
交换并删除: Θ(1)+ Θ(1)
调整为堆:O(logn)
习题6.5
1.
乘法总次数M(n)
加法总次数A(n)
习题7.1
3.假设列表的可能值属于集合{a,b,c,d},用分布计数算法对下面的列表按照字母顺序排序.
b,c,d,c,b,a,a,b
解:
输入A: b,c,d,c,b,a,a,b
频率:
分布值:
4.分布计数算法是稳定的吗?
是稳定的.
因为算法从右至左扫描输入,等值元素也是被从右至左地放入排序好的数组里.
习题7.2
1. 应用Horspool算法在下面的文本中查找模式BAOBAB:
BESS_KNEW_ABOUT_BAOBABS
解:字符移动表:
匹配过程:
4.用Horspool算法在一个长度为n的文本中查找一个长度为m的模式,请分别给出下面两种例子.
a.最差输入 b.最优输入
hints:
a. 在n个”0”组成的文本中查找”10..0”(长度为m),查找次数Cw=m(n-m+1)
b. 在n个”0”组成的文本中查找由m个”0”组成的模式,查找次数Cb=m
习题7.3
1. 对于输入30,20,56,75,31,19和散列函数h(K)=Kmod11
a. 构造它们的开散列表
b. 求在本表中成功查找的最大键值比较次数
c. 求在本表中成功查找的平均比较次数
Hints:
键值列表: 30,20,56,75,31,19
Hash 函数: h(K)=Kmod11
Hash 地址:
开散列表:
b.3(查找键值31)
c.
2.(题略)
a. 键值列表: 30,20,56,75,31,19
Hash 函数: h(K)=Kmod11
Hash 地址:
闭散列表:
b.6(查找键值19)
c.
第8章 动态规划
习题8.1
1.a.动态规划与分治法有什么共同点?(基于分解为更小的子问题)
b.这两种技术之间有什么主要的不同点?
分治法分解出的子问题相对独立,而动态规划则相互交叠;
分治法通常不需要保存子问题的结果,而动态规划则保存
2. a.应用动态规划求解C(6,3)
b. 为了计算C(n,k),需要填充算法的动态规划表,在填表时是否可以一列接一列地填,而不是一行接一行地填?
解:a.
b.可以.每一列从主对线由1开始,自上而下填表.
3.证明:
解:
对n,k>=0,显然:
成立.
对n>=2,
0<=k<=n,则有:
习题8.2
1.对由下面邻接矩阵定义的有向图,应用warshall算法求它的传递闭包
解:
3. 如果不使用额外的存储空间来存储warshall算法中间矩阵的元素,如何实现?
Hints:
Warshall算法计算新矩阵是按下面的递推关系:
可以看出从R(k-1)生成R(k)时,第k行和第k列的并没有改变.因此,对每个i,j来说,第i行第j列的新值R(k)[i,j]可以覆盖对应位置上的R(k-1)[i,j]
4. 如何重构warshall算法最内层循环,使得它到少对于某此输入来说运行得列快?
hints:
如果R(k-1)[i,k]=0,那么
,则不需要进行最内层循环.
由于R(k-1)[i,k]不依赖于j,所以R(k-1)[i,k]=0这个判断可以在最内层j循环外面进行.算法改进如下:
Warshall2(A[1..n,1..n])
//内层循环更有效的Warshall 算法
//输入:n节点的有向图的邻接矩阵A
//输出:该图的传递闭包A
for k←1 to n do
for i←1
to n do
if A[i,k]
for j←1 to n do
if A[k,j]
A[i,j]=true
Return A
习题8.3
1.完成本节构造最优二叉查找树例题中余下的计算.
解:
2.a. 算法optimalBST的时间效率为什么是立方级?
b. 算法optimalBST的空间效率为什么是平方级?
解:a.最内层循环执行的次数:
b. 算法optimalBST使用了两个表:C--(n+1)×(n+1),R--n×n,并且每个表只填了一半.
3.写一个线性时间算法的伪代码,来从根表中生成最优二叉查找树
Algorithms OptimalTree(i,j)
//输入:有序列表的第一和最后序号
//输入:先序遍历最优二叉查找树节点编号的列表
习题9.1
1、 给出一个找零问题的实例,使得贪婪算法不能输出一个最优解.
2、 为找零问题写一个贪婪算法的伪代码,它以金额n和硬币的面额d1>d2>…>dm作为输入.以n的函数形式给出该算法的效率类型.
Hints:
Algorithms change(n,D[1..m])
//用贪婪法求找零问题
//输入:非负整数n,硬币面额以降序排列的数组D
//输出:数组A[1..m]----每种面额硬币的数量,或者无解
习题9.4
1.(题略)
a.
b.
c.
b.该问题的实例中共有多少个不同的最优子集?
解答:只有一个,为{0,0,1,0,1}
c.一般来说,如何从动态规划算法所生成的表中判断背包问题的实例是不是具有不止一个最优子集?
解答:一般来说,可以通过判断表中最后一列的最大值个数来判断,因为背包问题的最优值的产生只会在最后一列产生。