算法导论第七章练习参考答案

Exercises

7.3-1 为什么我们分析随机化算法的期望运行时间,而不是最坏运行时间呢?

随机化算法并不会改善最坏情况的运行时间,但是会减少最坏情况发生的概率。

7.3-2 在RANDOMIZED-QUICKSORT的运行过程中,在最坏情况下,随机数生成器RANDOM被调用了多少次?在最好情况下呢?以 Θ \Theta Θ符号的形式给出你的答案?

因为排列 n n n个数最好情况和最坏情况下都需要选取 n − 1 n-1 n1次主元,所以

最坏情况下: Θ ( n ) \Theta(n) Θ(n)

最好情况下: Θ ( n ) \Theta(n) Θ(n)

7.4-1 证明:在递归式
T ( n ) = m a x ( T ( q ) + T ( n − q − 1 ) ) + Θ ( n ) T(n)=max(T(q)+T(n-q-1))+\Theta(n) T(n)=max(T(q)+T(nq1))+Θ(n)
中, T ( n ) = Ω ( n 2 ) T(n)=\Omega(n^2) T(n)=Ω(n2)

假设 T ( n ) ≥ c n 2 T(n)\geq cn^2 T(n)cn2,则 T ( n ) ≥ m a x ( c q 2 + c ( n − q − 1 ) 2 ) + Θ ( n ) T(n)\geq max(cq^2+c(n-q-1)^2) +\Theta(n) T(n)max(cq2+c(nq1)2)+Θ(n)

q 2 + ( n − 1 − q ) 2 q^2+(n-1-q)^2 q2+(n1q)2的最大值在两端点处取得,我们有 T ( n ) ≥ c ( n − 1 ) 2 + Θ ( n ) = c n 2 − c ( 2 n − 1 ) + Θ ( n ) T(n)\geq c(n-1)^2+\Theta(n)=cn^2-c(2n-1)+\Theta(n) T(n)c(n1)2+Θ(n)=cn2c(2n1)+Θ(n)

只要取足够小的正常数c,使得 c ( 2 n − 1 ) ≤ Θ ( n ) c(2n-1)\leq \Theta(n) c(2n1)Θ(n),就有 T ( n ) ≥ c n 2 T(n) \geq cn^2 T(n)cn2,即 T ( n ) = Ω ( n 2 ) T(n)=\Omega(n^2) T(n)=Ω(n2)

7.4-2 证明:在最好情况下,快速排序的运行时间为 Ω ( l g n ) \Omega(lgn) Ω(lgn)

最好情况下,有递归式: T ( n ) = 2 T ( n / 2 ) + Θ ( n ) T(n)=2T(n/2)+\Theta(n) T(n)=2T(n/2)+Θ(n)

假设 T ( n ) ≥ c n l g n T(n)\geq cnlgn T(n)cnlgn,则 T ( n ) ≥ 2 c n 2 l g n 2 + Θ ( n ) = 2 c n l g n − 2 c n + Θ ( n ) T(n)\geq 2c\frac{n}{2}lg\frac{n}{2}+\Theta(n)=2cnlgn-2cn+\Theta(n) T(n)2c2nlg2n+Θ(n)=2cnlgn2cn+Θ(n)

只要取足够小的正常数c,使得 2 c n < Θ ( n ) 2cn\lt \Theta(n) 2cn<Θ(n),就有 T ( n ) ≥ c n l g n T(n)\geq cnlgn T(n)cnlgn,即 T ( n ) = Ω ( n l g n ) T(n)=\Omega(nlgn) T(n)=Ω(nlgn)

7.4-3 证明:在 q = 0 , 1 , ⋯   , n − 1 q=0,1,\cdots,n-1 q=0,1,,n1区间内,当 q = 0 q=0 q=0 q = n − 1 q=n-1 q=n1时, q 2 + ( n − q − 1 ) 2 q^2+(n-q-1)^2 q2+(nq1)2取得最大值。

f ( q ) = q 2 + ( n − 1 − q ) 2 f(q)=q^2+(n-1-q)^2 f(q)=q2+(n1q)2,则有 f ′ ( q ) = 4 q − 2 ( n − 1 ) , f ′ ′ f^\prime(q)=4q-2(n-1),f^{\prime\prime} f(q)=4q2(n1),f(q)=4, f ( q ) f(q) f(q) ( 0 , n − 1 2 ) (0,\frac{n-1}{2}) (0,2n1)上单调递减,在 ( 0 , n − 1 2 ) (0,\frac{n-1}{2}) (0,2n1)上单调增加,在 q = n − 1 2 q=\frac{n-1}{2} q=2n1上取得极小值,在两端点处取得最大值 f ( 0 ) = f ( n − 1 ) = ( n − 1 ) 2 f(0)=f(n-1)=(n-1)^2 f(0)=f(n1)=(n1)2

7.4-4 证明:RANDOMIZED-QUICKSORT的期望运行时间是 Ω ( n l g n ) \Omega(nlgn) Ω(nlgn)

7.4-5 当输入数据已经“几乎有序”时,插入排序速度很快。在实际应用中,我们可以利用这一特点来提高快速排序的速度。当对一个长度小于 k k k的子数组调用快速排序时,让它不做任何排序就返回。当上层的快速排序调用返回后,对整个数组运行插入排序来完成排序过程。试证明:这一排序算法的期望复杂度为 O ( n k + n l o g ( n / k ) ) O(nk+nlog(n/k)) O(nk+nlog(n/k))。分别从理论和实践的角度说明我们应该如何选择 k k k

算法代码如下:

QUICKSORTWITHINSERTIONSORT(A,p,r)
	QUICKSORT(A,p,r)
	INSERTION-SORT(A,p,r)//整体进行插入排序O(nk)
QUICKSORT(A,p,r)
	if r-p+1>k //长度小于k的子数组直接返回
		q=PARTITION(A,p,r)
		QUICKSORT(A,p,q-1)
		QUICKSORT(A,q+1,r)

总体排序时间时快速排序和插入排序总和。快速排序递归树递归到 T ( k ) T(k) T(k)为止,递归树高度此时为 O ( l o g n − l o g k ) O(logn-logk) O(lognlogk),每层划分花费 O ( n ) O(n) O(n),一共 O ( n l o g ( n / k ) ) O(nlog(n/k)) O(nlog(n/k))。插入排序时,每个元素的移动不会超过 k − 1 k-1 k1次,时间复杂度为 O ( n k ) O(nk) O(nk)。所以总的时间复杂度为 O ( n k + n l o g ( n / k ) ) O(nk+nlog(n/k)) O(nk+nlog(n/k))

理论上不要超过快速排序的平均时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。实践中, k k k [ 1 , l o g n ] [1,logn] [1,logn]之间取值。

Problems

7.4 (快速排序的栈深度)7.1节中的QUICKSORT算法包含了两个对其自身的递归调用。在调用PARTITION后,QUICKSORT分别递归调用了左边的子数组和右边的子数组。QUICKSORT中第二个递归调用不是必须的。我们可以用一个循环空值结构来代替它。这一技术成为尾递归,好的编译器都提供这一功能。考虑下面这个版本的快速排序,它模拟了尾递归的情况:

TAIL-RECURSIVE-QUICKSORT(A,p,r)
while p < r
	//Partition and sort left subarray.
    q-PARTITION(A,p,r)
    TAIL-RECURSIVE-QUICKSORT(A,p,q-1)
    p=q+1

a.证明:TAIL-RECURSIVE-QUICKSORT(A,1,A.length)能正确地对数组A进行排序。编译器通常使用栈来存储递归执行过程中的信息,包括每一次递归调用的参数等。最新调用的信息存在栈的顶部,而第一次调用的信息存在栈的底部。当一个过程被调用时,其相关信息被压入栈中;当它结束时,其信息被弹出。因为我们假设数组参数是用指针来指示的,所以每次过程调用只需要 O ( 1 ) O(1) O(1)的栈空间。栈深度是在一次计算中会用到的栈空间的最大值。

b.请描述一种场景,使得针对一个包含 n n n个元素数组的TAIL-RECURSIVE-QUICKSORT的栈深度是 Θ ( n ) \Theta(n) Θ(n)

输入序列是 A = < 1 , 2 , 3 , 4 , ⋯   , n > A=<1,2,3,4,\cdots,n> A=<1,2,3,4,,n>时,栈深度是 Θ ( n ) \Theta(n) Θ(n)

c.修改TAIL-RECURSIVE-QUICKSORT的代码,使其最坏情况下栈深度是 Θ ( l g n ) \Theta(lgn) Θ(lgn),并且能够保持 O ( n l g n ) O(nlgn) O(nlgn)的期望时间复杂度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值