本文最后更新于:2024年6月8日 上午
算法设计技巧与分析-课后作业
前言:本文为NUAA《算法设计技巧与分析》课程配套教材的课后作业,由于这本教材很难找到答案,所以Po上部分我自己以及老师的答案,仅供参考~
教材长啥样
第1章 算法分析基本概念
1.9 证明观察结论1.4
1 2 3 4 5 6 7 8 for (int i=2 ;i<=n;i++) x=A[i]; j=i-1 ; while (j>0 && A[j]>x) A[j+1 ]=A[j]; j=j-1 ; A[j+1 ]=x;
对于for
循环内的while
循环
当while
循环都是因为A[j]>x
不满足而跳出循环时,
对于每一次for
循环,其执行的
赋值次数 = 1 (x=A[i]) + 比较次数 (A[j]>x) - 1 (最后一次比较没有赋值) + 1 (A[j+1]=x)
= 1 + 比较次数
而for
循环执行了n-1
次,因此这种情况下,总元素赋值次数= n-1 + 总元素比较次数
当while
循环是因为j>0
不满足而跳出循环时,此结论并不成立
1.17 BUBBLESORT
元素的最少比较次数是n − 1 n-1 n − 1 次,在非降序排列时达到最小值
元素的最多比较次数是n ( n − 1 ) 2 \frac{n(n-1)}{2} 2 n ( n − 1 ) 次,在非升序排列时达到最大值
元素的最少赋值次数是0 0 0 次,在非降序排列时达到最小值
元素的最多赋值次数是3 n ( n − 1 ) 2 \frac{3n(n-1)}{2} 2 3 n ( n − 1 ) 次,在非升序排列时达到最大值
T = O ( n 2 ) , T = Ω ( n ) T=O(n^2),T=\Omega(n) T = O ( n 2 ) , T = Ω ( n )
不可以用Θ \Theta Θ 符号来表示,因为该算法的运行时间由线性到平方排列,不能精确表示
1.20 证明∑ j = 1 n j k = O ( n k + 1 ) , ∑ j = 1 n j k = Ω ( n k + 1 ) → ∑ j = 1 n j k = Θ ( n k + 1 ) \sum_{j=1}^{n}j^k=O(n^{k+1}),\sum_{j=1}^{n}j^k=\Omega(n^{k+1})\rightarrow\sum_{j=1}^{n}j^k=\Theta(n^{k+1}) ∑ j = 1 n j k = O ( n k + 1 ) , ∑ j = 1 n j k = Ω ( n k + 1 ) → ∑ j = 1 n j k = Θ ( n k + 1 )
证明:
∑ j = 1 n j k = 1 k + 2 k + 3 k + . . . + n k < = n k + n k + n k + . . . + n k = n ⋅ n k = n k + 1 \sum_{j=1}^{n}j^{k}=1^k+2^k+3^k+...+n^k<=n^k+n^k+n^k+...+n^k=n\cdot n^k=n^{k+1}
j = 1 ∑ n j k = 1 k + 2 k + 3 k + ... + n k <= n k + n k + n k + ... + n k = n ⋅ n k = n k + 1
因此∑ j = 1 n j k = O ( n k + 1 ) \sum^{n}_{j=1}j^k=O(n^{k+1}) ∑ j = 1 n j k = O ( n k + 1 )
而
∑ j = 1 n j k = 1 k + 2 k + 3 k + . . . + ⌊ n 2 ⌋ k + . . . + ( ⌊ n 2 ⌋ + 1 ) k + . . . + n k > = ( n 2 ) k + . . . + ( n 2 ) k ⏟ ⌊ n 2 ⌋ = ⌊ n 2 ⌋ ( n 2 ) k \begin{align*}\sum_{j=1}^{n}j^k&=1^k+2^k+3^k+...+\lfloor{\frac{n}{2}}\rfloor ^{k}+...+(\lfloor{\frac{n}{2}}\rfloor+1) ^{k}+...+n^{k} \\ &>=\underbrace{(\frac{n}{2})^k+...+(\frac{n}{2})^k}_{\lfloor \frac{n}{2}\rfloor}= \lfloor \frac{n}{2}\rfloor(\frac{n}{2})^{k}\end{align*}
j = 1 ∑ n j k = 1 k + 2 k + 3 k + ... + ⌊ 2 n ⌋ k + ... + (⌊ 2 n ⌋ + 1 ) k + ... + n k >= ⌊ 2 n ⌋ ( 2 n ) k + ... + ( 2 n ) k = ⌊ 2 n ⌋ ( 2 n ) k
即∑ j = 1 n j k = Ω ( n k + 1 ) \sum^{n}_{j=1}j^k=\Omega(n^{k+1}) ∑ j = 1 n j k = Ω ( n k + 1 )
因此∑ j = 1 n j k = Θ ( n k + 1 ) \sum^{n}_{j=1}j^k=\Theta(n^{k+1}) ∑ j = 1 n j k = Θ ( n k + 1 )
1.29 给出增长率次序
( 1 2 ) n ≺ 5 ≺ l o g l o g n ≺ l o g n 100 ≺ l o g 2 n ≺ n 1 100 ≺ n ≺ n l o g n ≺ ( n ) n ≺ n ! ≺ 2 n 2 (\frac{1}{2})^n\prec 5\prec loglogn\prec log n^{100}\prec log^2n \prec n^{\frac{1}{100}} \prec \sqrt{n}\prec nlog n\prec {\color{red}(\sqrt{n})^{n}\prec n!}\prec2^{n^2}
( 2 1 ) n ≺ 5 ≺ l o g l o g n ≺ l o g n 100 ≺ l o g 2 n ≺ n 100 1 ≺ n ≺ n l o g n ≺ ( n ) n ≺ n ! ≺ 2 n 2
l i m n → ∞ n ! n n = l i m n → ∞ 2 π n ( n e ) n n n / 2 = l i m n → ∞ 2 π n e − n n n / 2 = l i m n → ∞ 2 π n ( n e 2 ) n / 2 = ∞ \begin{align*}lim_{n\rightarrow\infty}\frac{n!}{\sqrt{n}^n}&=lim_{n\rightarrow\infty}\frac{\sqrt{2\pi n}(\frac{n}{e})^n}{n^{n/2}}\\&=lim_{n\rightarrow\infty}\sqrt{2\pi n}e^{-n}n^{n/2}\\&=lim_{n\rightarrow\infty}\sqrt{2\pi n}(\frac{n}{e^2})^{n/2}=\infty\end{align*}
l i m n → ∞ n n n ! = l i m n → ∞ n n /2 2 πn ( e n ) n = l i m n → ∞ 2 πn e − n n n /2 = l i m n → ∞ 2 πn ( e 2 n ) n /2 = ∞
1.32 考虑算法COUNT6,输入正整数n
(a)第6步执行次数为
6 ∑ i = 1 ⌊ l o g n ⌋ i 2 = 6 ⋅ ( ⌊ l o g n ⌋ ) ( ⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) 6 = ( ⌊ l o g n ⌋ ) ( ⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) \begin{align*}6\sum_{i=1}^{\lfloor log n\rfloor}i^2 &= 6\cdot \frac{(\lfloor logn\rfloor)(\lfloor logn\rfloor+1)(2\lfloor logn\rfloor+1)}{6} \\&=(\lfloor logn\rfloor)(\lfloor logn\rfloor+1)(2\lfloor logn\rfloor+1)\end{align*}
6 i = 1 ∑ ⌊ l o g n ⌋ i 2 = 6 ⋅ 6 (⌊ l o g n ⌋) (⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) = (⌊ l o g n ⌋) (⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 )
(b)用Θ \Theta Θ 更合适,因为
⌊ l o g n ⌋ 3 < = ⌊ l o g n ⌋ ( ⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) < = 3 ⌊ l o g n ⌋ 3 \begin{align*}\lfloor logn \rfloor^3<=\lfloor logn\rfloor(\lfloor logn\rfloor+1)(2\lfloor logn\rfloor+1)<=3\lfloor logn \rfloor^3\end{align*}
⌊ l o g n ⌋ 3 <= ⌊ l o g n ⌋ (⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) <= 3 ⌊ l o g n ⌋ 3
即⌊ l o g n ⌋ ( ⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) = Θ ( ⌊ l o g n ⌋ 3 ) \lfloor logn\rfloor(\lfloor logn\rfloor+1)(2\lfloor logn\rfloor+1)=\Theta (\lfloor logn \rfloor^3) ⌊ l o g n ⌋ (⌊ l o g n ⌋ + 1 ) ( 2 ⌊ l o g n ⌋ + 1 ) = Θ (⌊ l o g n ⌋ 3 )
(c)是Θ ( ⌊ l o g n ⌋ 3 ) \Theta (\lfloor logn \rfloor^3) Θ (⌊ l o g n ⌋ 3 )
1.35 设计一个算法,找出存储在数组A[1…n]中的n个整数的最大值和最小值,使得它的时间复杂度分别是(a)O ( n ) O(n) O ( n ) (b)Ω ( n l o g n ) \Omega(nlog n) Ω ( n l o g n )
O ( n ) O(n) O ( n )
1 2 3 4 5 6 maxnum = A[1 ]minnum = A[1 ] for i= 2 to n if (A[i] > maxnum) then maxnum = A[i] if (A[i] < minnum) then minnum = A[i] end for
该算法的迭代次数为n − 1 n-1 n − 1 ,故时间复杂度为O ( n ) O(n) O ( n )
Ω ( n l o g n ) \Omega(nlogn) Ω ( n l o g n )
1 2 3 BOTTOMUPSORT (A,1 ,n) maxnum = A[n] minnum = A[1]
BOTTOMUPSORT的时间复杂度为Θ ( n l o g n ) \Theta(nlogn) Θ ( n l o g n ) ,因此该算法的时间复杂度也为Ω ( n l o g n ) \Omega(nlogn) Ω ( n l o g n )
1.38 设计算法在给定时间复杂度下求a n x n + a n − 1 x n − 1 + . . . + a 1 x + a 0 a_nx^n+a_{n-1}x^{n-1}+...+a_1x+a_0 a n x n + a n − 1 x n − 1 + ... + a 1 x + a 0 的值
假设数组A [ 0 , 1 , 2 , . . . , n ] A[0,1,2,...,n] A [ 0 , 1 , 2 , ... , n ] 存放a 0 , a 1 , . . . , a n a_0,a_1,...,a_n a 0 , a 1 , ... , a n
Ω ( n 2 ) \Omega(n^2) Ω ( n 2 )
1 2 3 4 5 6 7 8 9 10 sum = A[0 ]for i=1 to n temp = 1 for j=1 to i temp = temp * x j = j + 1 end for sum = sum + A[i] * temp i = i + 1 end for
该算法的迭代次数为∑ i = 1 n i = n ( n + 1 ) 2 \sum_{i=1}^{n}i=\frac{n(n+1)}{2} ∑ i = 1 n i = 2 n ( n + 1 ) ,故时间复杂度为Ω ( n 2 ) \Omega(n^2) Ω ( n 2 )
O ( n ) O(n) O ( n )
1 2 3 4 5 sum = 0 for i=n to 0 sum = sum * x + A[i] i = i - 1 end for
该算法的迭代次数为n + 1 n+1 n + 1 ,故时间复杂度为O ( n ) O(n) O ( n )
1.39 设计算法将具有n (n为偶数) 个正整数的集合S划分为有n 2 \frac{n}{2} 2 n 个数的集合S1和S2,且S1中所有元素的和与S2中所有元素的和差值最大。
算法如下:
1 2 3 4 5 6 7 BOTTOMUPSORT (S,1 ,n)for i=1 to n/2 S1 [i] = S[i]end forfor i=n/2 to n S2 [i-n/2 +1 ] = S[i]end for
该算法首先对S进行BOTTOMUPSORT排序(升序),将排序后的S前n/2个元素赋值给S1,后n/2个元素赋值给S2,此时S1中所有元素的和与S2中所有元素的和差值最大。
由于BOTTOMUPSORT的时间复杂度为Θ ( n l o g n ) \Theta(nlogn) Θ ( n l o g n ) ,而后迭代n n n 次,故总时间复杂度仍为Θ ( n l o g n ) \Theta(nlogn) Θ ( n l o g n )
第2章 数学预备知识
A.12 用归纳法证明对于n ≥ 4 , n ! > 2 n n\ge 4,n!>2^n n ≥ 4 , n ! > 2 n
当n = 4 n=4 n = 4 时,4 ! = 24 > 2 4 = 16 4!=24>2^4=16 4 ! = 24 > 2 4 = 16 ,该结论成立。
假设当n = k n=k n = k 时,有此结论成立:
k ! > 2 k 则 ( k + 1 ) k ! > ( k + 1 ) 2 k > 2 ⋅ 2 k 即 ( k + 1 ) ! > 2 k + 1 \begin{align*}k! &>2^k \\ 则 (k+1)k!&>(k+1)2^k >2\cdot2^k \\ 即 (k+1)!&>2^{k+1} \end{align*}
k ! 则 ( k + 1 ) k ! 即 ( k + 1 )! > 2 k > ( k + 1 ) 2 k > 2 ⋅ 2 k > 2 k + 1
即对于n = k + 1 n=k+1 n = k + 1 ,该结论也成立。
因此对于n ≥ 4 , n ! > 2 n n\ge 4,n!>2^n n ≥ 4 , n ! > 2 n
A.17 分别用(a)代数方法(b)积分近似求和方法,证明∑ j = 1 n l o g ( n j ) = O ( n ) \sum_{j=1}^{n}log(\frac{n}{j})=O(n) ∑ j = 1 n l o g ( j n ) = O ( n )
代数方法
首先∑ j = 1 n l o g j = ∑ j = 2 n l o g j > = ∫ 1 n l o g x d x = n l o g n − n l o g e + l o g e \sum_{j=1}^{n}logj=\sum_{j=2}^{n}logj>=\int_{1}^{n}logxdx=nlogn-nloge+loge ∑ j = 1 n l o g j = ∑ j = 2 n l o g j >= ∫ 1 n l o gx d x = n l o g n − n l o g e + l o g e
∑ j = 1 n l o g ( n j ) = ∑ j = 1 n l o g n − ∑ j = 1 n l o g j = n l o g n − ∑ j = 1 n l o g j ≤ n l o g n − ( n l o g n − n l o g e + l o g e ) = n l o g e − l o g e \begin{align*}\sum_{j=1}^{n}log(\frac{n}{j})&=\sum_{j=1}^{n}logn-\sum_{j=1}^{n}logj\\ &=nlogn-\sum_{j=1}^{n}logj\\ &\le nlogn-(nlogn-nloge+loge)\\&=nloge-loge\end{align*}
j = 1 ∑ n l o g ( j n ) = j = 1 ∑ n l o g n − j = 1 ∑ n l o g j = n l o g n − j = 1 ∑ n l o g j ≤ n l o g n − ( n l o g n − n l o g e + l o g e ) = n l o g e − l o g e
因此∑ j = 1 n l o g ( n j ) = O ( n ) \sum_{j=1}^{n}log(\frac{n}{j})=O(n) ∑ j = 1 n l o g ( j n ) = O ( n )
更正:
n ! ≥ e ( n e ) n l o g n n n ! ≤ l o g e n − 1 = ( n − 1 ) l o g e {n!\ge e(\frac{n}{e})^n}\\
log\frac{n^n}{n!}\le loge^{n-1}=(n-1)loge
n ! ≥ e ( e n ) n l o g n ! n n ≤ l o g e n − 1 = ( n − 1 ) l o g e
积分近似求和方法
由于f ( x ) = l o g ( n x ) f(x)=log(\frac{n}{x}) f ( x ) = l o g ( x n ) 是递减的,有
∑ j = 1 n l o g ( n j ) = l o g n + ∑ j = 2 n l o g ( n j ) < = l o g n + ∫ 1 n l o g ( n x ) d x \begin{align*} \sum_{j=1}^{n}log(\frac{n}{j})=logn+\sum_{j=2}^{n}log(\frac{n}{j})<=logn+\int_{1}^{n}log(\frac{n}{x}) dx \end{align*}
j = 1 ∑ n l o g ( j n ) = l o g n + j = 2 ∑ n l o g ( j n ) <= l o g n + ∫ 1 n l o g ( x n ) d x
即
∑ j = 1 n l o g ( n j ) < = ( n − 1 ) l o g e \sum_{j=1}^{n}log(\frac{n}{j})<=(n-1)loge
j = 1 ∑ n l o g ( j n ) <= ( n − 1 ) l o g e
因此∑ j = 1 n l o g ( n j ) = O ( n ) \sum_{j=1}^{n}log(\frac{n}{j})=O(n) ∑ j = 1 n l o g ( j n ) = O ( n )
A.18 求解递推关系
f ( n ) = 2 f ( n − 1 ) f(n)=2f(n-1) f ( n ) = 2 f ( n − 1 ) ,当n ≥ 1 n\ge1 n ≥ 1 ;f ( 0 ) = 2 f(0)=2 f ( 0 ) = 2
由于
f ( n ) = 2 f ( n − 1 ) = 2 ( 2 f ( n − 2 ) ) = . . . = 2 n f ( 0 ) \begin{align*}f(n)&=2f(n-1)\\&=2(2f(n-2))\\&=...\\&=2^{n}f(0)\end{align*}
f ( n ) = 2 f ( n − 1 ) = 2 ( 2 f ( n − 2 )) = ... = 2 n f ( 0 )
即f ( n ) = 2 n + 1 f(n)=2^{n+1} f ( n ) = 2 n + 1
f ( n ) = 5 f ( n − 1 ) f(n)=5f(n-1) f ( n ) = 5 f ( n − 1 ) ,当n ≥ 1 n\ge1 n ≥ 1 ;f ( 0 ) = 1 f(0)=1 f ( 0 ) = 1
由于
f ( n ) = 5 f ( n − 1 ) = 5 ( 5 f ( n − 2 ) ) = . . . = 5 n f ( 0 ) \begin{align*}f(n)&=5f(n-1)\\&=5(5f(n-2))\\&=...\\&=5^{n}f(0)\end{align*}
f ( n ) = 5 f ( n − 1 ) = 5 ( 5 f ( n − 2 )) = ... = 5 n f ( 0 )
即f ( n ) = 5 n f(n)=5^{n} f ( n ) = 5 n
A.19 求解递推关系
f ( n ) = 6 f ( n − 1 ) − 8 f ( n − 2 ) , 当 n ≥ 2 ; f ( 0 ) = 1 , f ( 1 ) = 0 f(n)=6f(n-1)-8f(n-2),当n\ge 2;f(0)=1,f(1)=0 f ( n ) = 6 f ( n − 1 ) − 8 f ( n − 2 ) , 当 n ≥ 2 ; f ( 0 ) = 1 , f ( 1 ) = 0
特征方程为x 2 − 6 x + 8 = 0 x^2-6x+8=0 x 2 − 6 x + 8 = 0 ,解为x 1 = 2 , x 2 = 4 x_1=2,x_2=4 x 1 = 2 , x 2 = 4 .
因此
f ( n ) = c 1 2 n + c 2 4 n { c 1 + c 2 = 1 2 c 1 + 4 c 2 = 0 c 1 = 2 , c 2 = − 1 \begin{align*} f(n)=c_12^n+c_24^n \\ \begin{cases}
{c_1+c_2=1} \\
{2c_1+4c_2=0}
\end{cases}\\c_1=2,c_2=-1\end{align*}
f ( n ) = c 1 2 n + c 2 4 n { c 1 + c 2 = 1 2 c 1 + 4 c 2 = 0 c 1 = 2 , c 2 = − 1
即f ( n ) = 2 n + 1 − 4 n f(n)=2^{n+1}-4^{n} f ( n ) = 2 n + 1 − 4 n
f ( n ) = − 6 f ( n − 1 ) − 9 f ( n − 2 ) , 当 n ≥ 2 ; f ( 0 ) = 3 , f ( 1 ) = − 3 f(n)=-6f(n-1)-9f(n-2),当n\ge 2;f(0)=3,f(1)=-3 f ( n ) = − 6 f ( n − 1 ) − 9 f ( n − 2 ) , 当 n ≥ 2 ; f ( 0 ) = 3 , f ( 1 ) = − 3
特征方程为x 2 + 6 x + 9 = 0 x^2+6x+9=0 x 2 + 6 x + 9 = 0 ,解为x 1 = x 2 = − 3 x_1=x_2=-3 x 1 = x 2 = − 3 .
因此
f ( n ) = c 1 ( − 3 ) n + c 2 n ( − 3 ) n { c 1 = 3 − 3 c 1 − 3 c 2 = − 3 c 1 = 3 , c 2 = − 2 \begin{align*} f(n)&=c_1(-3)^n+c_2n(-3)^n \\ &\begin{cases}
{c_1=3} \\
{-3c_1-3c_2=-3}
\end{cases}\\&c_1=3,c_2=-2\end{align*}
f ( n ) = c 1 ( − 3 ) n + c 2 n ( − 3 ) n { c 1 = 3 − 3 c 1 − 3 c 2 = − 3 c 1 = 3 , c 2 = − 2
即f ( n ) = ( − 1 ) n 3 n + 1 − 2 n ( − 3 ) n = ( − 3 ) n ( 3 − 2 n ) f(n)=(-1)^n3^{n+1}-2n(-3)^{n}=(-3)^n(3-2n) f ( n ) = ( − 1 ) n 3 n + 1 − 2 n ( − 3 ) n = ( − 3 ) n ( 3 − 2 n )
A.20 求解递推关系:f ( n ) = 2 f ( n − 1 ) + n + 4 , 当 n ≥ 1 ; f ( 0 ) = 4 f(n)=2f(n-1)+n+4,当n\ge1;f(0)=4 f ( n ) = 2 f ( n − 1 ) + n + 4 , 当 n ≥ 1 ; f ( 0 ) = 4
令f ( n ) = 2 n f ′ ( n ) , f ( 0 ) = f ′ ( 0 ) = 4 f(n)=2^{n}f'(n),f(0)=f'(0)=4 f ( n ) = 2 n f ′ ( n ) , f ( 0 ) = f ′ ( 0 ) = 4 ,则
2 n f ′ ( n ) = 2 ⋅ 2 n − 1 f ′ ( n − 1 ) + n + 4 ⇒ f ′ ( n ) = f ′ ( n − 1 ) + n + 4 2 n ⇒ f ′ ( n ) = f ′ ( 0 ) + ∑ i = 1 n i + 4 2 i = f ′ ( 0 ) + 6 − n + 6 2 n \begin{align*}2^nf'(n)&=2\cdot2^{n-1}f'(n-1)+n+4 \\\Rightarrow f'(n)&=f'(n-1)+\frac{n+4}{2^n} \\\Rightarrow f'(n)&=f'(0)+\sum_{i=1}^{n}\frac{i+4}{2^i}=f'(0)+6-\frac{n+6}{2^n}\end{align*}
2 n f ′ ( n ) ⇒ f ′ ( n ) ⇒ f ′ ( n ) = 2 ⋅ 2 n − 1 f ′ ( n − 1 ) + n + 4 = f ′ ( n − 1 ) + 2 n n + 4 = f ′ ( 0 ) + i = 1 ∑ n 2 i i + 4 = f ′ ( 0 ) + 6 − 2 n n + 6
因此f ( n ) = 2 n f ′ ( n ) = 2 n f ′ ( 0 ) + 2 n ⋅ 6 − n − 6 = 2 n + 2 − n + 6 ⋅ ( 2 n − 1 ) f(n)=2^nf'(n)=2^nf'(0)+2^n\cdot6-n-6=2^{n+2}-n+6\cdot(2^n-1) f ( n ) = 2 n f ′ ( n ) = 2 n f ′ ( 0 ) + 2 n ⋅ 6 − n − 6 = 2 n + 2 − n + 6 ⋅ ( 2 n − 1 )
A.23(1.47) 分别用展开法和定理1.3求解递推式:f ( n ) = 9 f ( n / 3 ) + n 2 , n > = 2 ; f ( 1 ) = 1 f(n)=9f(n/3)+n^2,n>=2;f(1)=1 f ( n ) = 9 f ( n /3 ) + n 2 , n >= 2 ; f ( 1 ) = 1 ,n为3的幂
展开法:
设k = l o g 3 n k=log_3n k = l o g 3 n
f ( n ) = 9 f ( n / 3 ) + n 2 = 9 ( 9 f ( n / 3 2 ) + n 2 / 3 2 ) + n 2 = 9 2 f ( n / 3 2 ) + 2 n 2 = 9 2 ( 9 f ( n / 3 3 ) + n 2 / 3 4 ) + 2 n 2 = 9 3 f ( n / 3 3 ) + 3 n 2 = . . . = 9 k f ( n / 3 k ) + k n 2 = 9 k f ( 1 ) + k n 2 = n 2 + n 2 l o g 3 n \begin{align*}f(n)&=9f(n/3)+n^2 \\ &=9(9f(n/3^2)+n^2/3^2)+n^2 \\ &=9^2f(n/3^2)+2n^2 \\ &=9^2(9f(n/3^3)+n^2/3^4)+2n^2 \\ &=9^3f(n/3^3)+3n^2 \\ &=... \\ &=9^kf(n/3^k)+kn^2 \\ &=9^kf(1)+kn^2 \\ &=n^2+n^2log_3n\end{align*}
f ( n ) = 9 f ( n /3 ) + n 2 = 9 ( 9 f ( n / 3 2 ) + n 2 / 3 2 ) + n 2 = 9 2 f ( n / 3 2 ) + 2 n 2 = 9 2 ( 9 f ( n / 3 3 ) + n 2 / 3 4 ) + 2 n 2 = 9 3 f ( n / 3 3 ) + 3 n 2 = ... = 9 k f ( n / 3 k ) + k n 2 = 9 k f ( 1 ) + k n 2 = n 2 + n 2 l o g 3 n
定理1.3:
d = 1 , a = 9 , c = 3 , b = 1 , x = 2 d=1,a=9,c=3,b=1,x=2 d = 1 , a = 9 , c = 3 , b = 1 , x = 2
由于a = 9 = 3 2 = c x a=9=3^2=c^x a = 9 = 3 2 = c x ,因此f ( n ) = b n x l o g c n + d n x = n 2 l o g 3 n + n 2 f(n)=bn^xlog_cn+dn^x=n^2log_3n+n^2 f ( n ) = b n x l o g c n + d n x = n 2 l o g 3 n + n 2
A.26(1.50) 用代入法求解递推式的上界
f ( n ) = { f ( ⌊ n / 4 ⌋ ) + f ( ⌊ 3 n / 4 ⌋ ) + n , n ≥ 4 4 , n < 4 f(n)=\begin{cases}f(\lfloor{n/4}\rfloor)+f(\lfloor{3n/4}\rfloor)+n,n\ge4\\4,n<4\end{cases}
f ( n ) = { f (⌊ n /4 ⌋) + f (⌊ 3 n /4 ⌋) + n , n ≥ 4 4 , n < 4
用O O O 符号表示解
解:
猜测对于某个d > 0 d>0 d > 0 ,有f ( n ) ≤ d n l o g n + 4 n f(n)\le dnlogn+4n f ( n ) ≤ d n l o g n + 4 n 对于所有的n ≥ 1 n\ge1 n ≥ 1 均成立。
因此对于n ≥ 4 n\ge 4 n ≥ 4 ,有
f ( n ) = f ( ⌊ n / 4 ⌋ ) + f ( ⌊ 3 n / 4 ⌋ ) + n ≤ d ⌊ n 4 ⌋ l o g ⌊ n 4 ⌋ + 4 ⌊ n 4 ⌋ + d ⌊ 3 n 4 ⌋ l o g ⌊ 3 n 4 ⌋ + 4 ⌊ 3 n 4 ⌋ + n ≤ d n 4 l o g 3 n 4 + d 3 n 4 l o g 3 n 4 + 5 n = d n l o g n + 3 4 d n l o g 3 − 2 d n + 5 n \begin{align*}f(n)&=f(\lfloor{n/4}\rfloor)+f(\lfloor{3n/4}\rfloor)+n\\ &\le d\lfloor\frac{n}{4}\rfloor log\lfloor\frac{n}{4}\rfloor+4\lfloor\frac{n}{4}\rfloor+d\lfloor\frac{3n}{4}\rfloor log\lfloor\frac{3n}{4}\rfloor+4\lfloor\frac{3n}{4}\rfloor+n\\ &\le d\frac{n}{4} log\frac{3n}{4}+d\frac{3n}{4} log\frac{3n}{4}+5n\\ &=dnlogn+\frac{3}{4}dnlog3-2dn+5n\end{align*}
f ( n ) = f (⌊ n /4 ⌋) + f (⌊ 3 n /4 ⌋) + n ≤ d ⌊ 4 n ⌋ l o g ⌊ 4 n ⌋ + 4 ⌊ 4 n ⌋ + d ⌊ 4 3 n ⌋ l o g ⌊ 4 3 n ⌋ + 4 ⌊ 4 3 n ⌋ + n ≤ d 4 n l o g 4 3 n + d 4 3 n l o g 4 3 n + 5 n = d n l o g n + 4 3 d n l o g 3 − 2 d n + 5 n
为了证明f ( n ) ≤ d n l o g n + 4 n f(n)\le dnlogn+4n f ( n ) ≤ d n l o g n + 4 n ,要让
3 4 d n l o g 3 − 2 d n + n ≤ 0 \frac{3}{4}dnlog3-2dn+n\le 0
4 3 d n l o g 3 − 2 d n + n ≤ 0
即
d ≥ 1 2 − 3 4 l o g 3 = 1.23 d\ge\frac{1}{2-\frac{3}{4}log3}=1.23
d ≥ 2 − 4 3 l o g 3 1 = 1.23
显然当n < 4 n<4 n < 4 时,f ( n ) = 4 ≤ 1.23 n l o g n + 4 n f(n)=4\le1.23nlogn+4n f ( n ) = 4 ≤ 1.23 n l o g n + 4 n
因此f ( n ) = O ( n l o g n ) f(n)=O(nlogn) f ( n ) = O ( n l o g n )
A.31(1.55) 用更换变元法求解递推式的渐进表现
f ( n ) = { f ( n / 2 ) + n , n ≥ 4 2 , n < 4 f(n)=\begin{cases}f(n/2)+\sqrt{n},n\ge4\\2,n<4\end{cases}
f ( n ) = { f ( n /2 ) + n , n ≥ 4 2 , n < 4
其中n具有形式2 2 k 2^{2^k} 2 2 k
解:设n = 2 t , t = 2 k n=2^{t},t=2^k n = 2 t , t = 2 k ,则
f ( 2 t ) = { f ( 2 t − 1 ) + 2 t , 2 t ≥ 4 2 , 2 t < 4 f(2^t)=\begin{cases}f(2^{t-1})+\sqrt{2^{t}},2^t\ge4\\2,2^t<4\end{cases}
f ( 2 t ) = { f ( 2 t − 1 ) + 2 t , 2 t ≥ 4 2 , 2 t < 4
那么g ( t ) = f ( 2 t ) , g(t)=f(2^t), g ( t ) = f ( 2 t ) , 则
g ( t ) = { g ( t − 1 ) + 2 t , t ≥ 2 2 , t < 2 g(t)=\begin{cases}g(t-1)+\sqrt{2^t},t\ge2\\2,t<2\end{cases}
g ( t ) = { g ( t − 1 ) + 2 t , t ≥ 2 2 , t < 2
因
g ( t ) = 2 t / 2 + g ( t − 1 ) = 2 t / 2 + 2 ( t − 1 ) / 2 + g ( t − 2 ) = . . . = ( 2 t / 2 + 2 ( t − 1 ) / 2 . . . + 2 2 / 2 ) + g ( 1 ) = 2 + ∑ i = 2 t 2 i / 2 = 2 + 2 ( t + 1 ) / 2 − 2 2 − 1 , t ≥ 2 \begin{align*}g(t)&=2^{t/2}+g(t-1)\\&=2^{t/2}+2^{(t-1)/2}+g(t-2)\\&=...\\&=(2^{t/2}+2^{(t-1)/2}...+2^{2/2})+g(1)\\&=2+\sum_{i=2}^{t}{2^{i/2}}=2+\frac{2^{(t+1)/2}-2}{\sqrt{2}-1},\ t\ge 2\end{align*}
g ( t ) = 2 t /2 + g ( t − 1 ) = 2 t /2 + 2 ( t − 1 ) /2 + g ( t − 2 ) = ... = ( 2 t /2 + 2 ( t − 1 ) /2 ... + 2 2/2 ) + g ( 1 ) = 2 + i = 2 ∑ t 2 i /2 = 2 + 2 − 1 2 ( t + 1 ) /2 − 2 , t ≥ 2
将n = 2 t , t = l o g n n=2^t,t=log\ n n = 2 t , t = l o g n 代入上式,得
f ( n ) = { ( 2 + 1 ) ⋅ ( 2 ( l o g 2 n ) / 2 − 2 ) + 2 , n ≥ 4 2 , n < 4 f(n)=\begin{cases}(\sqrt{2}+1)\cdot (2^{(log\ 2n)/2}-2)+2,n\ge 4 \\2,n<4 \end{cases}
f ( n ) = { ( 2 + 1 ) ⋅ ( 2 ( l o g 2 n ) /2 − 2 ) + 2 , n ≥ 4 2 , n < 4
因此f ( n ) = Θ ( 2 l o g 2 n ) f(n)=\Theta(\sqrt{2}^{log\ 2n}) f ( n ) = Θ ( 2 l o g 2 n )
第4章 堆和不相交集数据结构
4.5(3.5) 编写算法判断给定数组A[1…n]是否是一个堆;给出其时间复杂性
1 2 3 4 5 6 7 8 9 isHeap = True for i=1 to n/2 if key(A[i]) < key(A[2 *i]) isHeap=False break if 2 *i+1 <=n and key(A[i] < key(A[2 *i+1 ]) isHeap=False break return isHeap
由于该算法最多比较⌊ n / 2 ⌋ \lfloor n/2\rfloor ⌊ n /2 ⌋ 次,因此该算法的时间复杂度为Θ ( n ) \Theta(n) Θ ( n )
4.13(3.13) 设A[1…19]是一个有19个整数的数组,对其MAKEHEAP
调用几次过程SIFT-DOWN?
⌊ 19 / 2 ⌋ = 9 \lfloor19/2\rfloor=9 ⌊ 19/2 ⌋ = 9
由于从9到1每次都要执行SIFT-DOWN函数,因此调用了9次过程SIFT-DOWN
元素交换的最大次数是多少?
考虑第i i i 个节点,其子节点为2 i 2^i 2 i ,则最多可交换1次
若子节点有子节点2 2 i 2^2i 2 2 i ,则最多交换2次
……
若…有子节点2 k i 2^ki 2 k i ,最多交换k次
因此有不等式2 k i < = 19 2^ki<=19 2 k i <= 19 ,对于以下i,求出其k:
i=1 k=4
i=2 k=3
i=3-4 k=2
i=5-9 k=1
因此共最多交换4+3+4+5=16次
给出有19个元素的数组,需要以上所述的元素交换最大次数
A[1…19]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}
即按升序排列的19个元素的数组
4.15(3.15)证明最坏情况下该建堆算法的运行时间是Θ ( n l o g n ) \Theta(n\ log\ n) Θ ( n l o g n ) 。给定整数数组A[1…n],建立A的堆B[1…n]:从空堆开始,反复将A中元素插入B,每一次调整当时的堆,直到B中包含A中所有的元素
考虑从1到n将元素插入B中,当插入第i
个元素后:
此时堆中有i
个元素,当前二叉堆的高度为⌊ l o g i ⌋ \lfloor log\ i\rfloor ⌊ l o g i ⌋
执行SIFT-UP操作需要的最多元素比较次数为⌊ l o g i ⌋ \lfloor log\ i\rfloor ⌊ l o g i ⌋ ,此为最坏情况
因此总共的元素比较次数为∑ i = 1 n ⌊ l o g i ⌋ \sum_{i=1}^{n}\lfloor log\ i\rfloor ∑ i = 1 n ⌊ l o g i ⌋ =Θ ( n l o g n ) \Theta(nlog\ n) Θ ( n l o g n )
4.19(3.19) 编写算法将两个相同大小的堆合并为一个,时间复杂性是多少?
设存在堆A[1…n]和堆B[1…n],新堆为C[1…2n]
1 2 3 4 5 6 7 for i=1 to n C[i] = A[i]for i=1 to n C[i+n] = B[i]for i=n downto 1 SIFT-DOWN(C,i)
该算法首先将A中的元素和B中的元素复制到新堆C中,再对C进行堆化操作
复制的次数为2 n 2n 2 n ,堆化的时间复杂度为Θ ( n ) \Theta(n) Θ ( n ) ,因此总时间复杂度为Θ ( n ) \Theta(n) Θ ( n )
4.22(3.22) 对于d堆的情况,重写SIFT-DOWN,以d和n为测度,它的时间复杂度是多少?
对于d堆,规定以下函数中变量d
为其堆数,数组A[1..n]
存储此堆
1 2 def d -ARY-PARENT(i) return floor((i - 2 ) / d + 1 )
1 2 def d -ARY-CHILD(i, j) return d*(i − 1 ) + j + 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def SIFT -DOWN(i) done=False if d-ARY-CHILD(i, 1 )>n return while (1 ) i=d-ARY-CHILD(i, 1 ) for j=1 to d-1 if i+j<=n and key(A[i+j])>key(A[i]) i=i+j if key(A[i])>key(A[d-ARY-PARENT(i)]) swap(A[i],A[d-ARY-PARENT(i)]) else done=True if done or d-ARY-CHILD(i, 1 )>n break
由于此d堆的高度最多为⌊ l o g d n ⌋ \lfloor log_dn\rfloor ⌊ l o g d n ⌋ ,每一次下移都会遍历d d d 个子节点,因此时间复杂度为O ( d l o g d n ) O(d\ log_d\ n) O ( d l o g d n )
第5章 归纳法
5.1(4.1) 给出一个计算第n个Fibonacci数f n f_n f n 的递归算法
f 1 = f 2 = 1 ; f n = f n − 1 + f n − 2 , 对于 n ≥ 3 f_1=f_2=1;f_n=f_{n-1}+f_{n-2},对于 n\ge 3
f 1 = f 2 = 1 ; f n = f n − 1 + f n − 2 , 对于 n ≥ 3
1 2 3 4 5 def GetFibonacci (n ): if n==1 or n==2 return 1 else return GetFibonacci(n-1 )+GetFibonacci(n-2 )
5.2(4.2) 给出一个计算第n个Fibonacci数f n f_n f n 的迭代算法
1 2 3 4 5 6 7 8 9 10 11 nfib=0 fn_1=fn_2=1 if n<3 nfib=1 else for i=3 to n nfib=fn_1+fn_2 fn_1=fn_2 fn_2=nfib endforreturn nfib
5.3(4.3) 用归纳法设计一个递归算法,在有n个元素的序列A[1…n]中寻找最大元素
1 2 3 4 5 6 7 def SearchMaxElem (left,right ): if right==left: return A[left] else : return max (A[right],SearchMaxElem(left,right-1 )) SearchMaxElem(1 ,n)
5.14(4.14) 用EXPREC计算
( a ) 2 5 ( b ) 2 7 ( c ) 3 5 ( d ) 5 7 (a)2^5\ \ (b)2^7\ \ (c)3^5\ \ (d)\ \ 5^7 ( a ) 2 5 ( b ) 2 7 ( c ) 3 5 ( d ) 5 7
2 5 2^5 2 5
2 5 = 2 ⋅ ( 2 2 ) 2 = 2 ⋅ ( 2 ⋅ 2 ) 2 = 32 2^5=2\cdot(2^2)^2=2\cdot(2\cdot2)^2=32 2 5 = 2 ⋅ ( 2 2 ) 2 = 2 ⋅ ( 2 ⋅ 2 ) 2 = 32
2 7 2^7 2 7
2 7 = 2 ⋅ ( 2 3 ) 2 = 2 ⋅ ( 2 ⋅ ( 2 ) 2 ) 2 = 128 2^7=2\cdot(2^3)^2=2\cdot(2\cdot(2)^2)^2=128 2 7 = 2 ⋅ ( 2 3 ) 2 = 2 ⋅ ( 2 ⋅ ( 2 ) 2 ) 2 = 128
3 5 3^5 3 5
3 5 = 3 ⋅ ( 3 2 ) 2 = 3 ⋅ ( 3 ⋅ 3 ) 2 = 243 3^5=3\cdot(3^2)^2=3\cdot(3\cdot3)^2=243 3 5 = 3 ⋅ ( 3 2 ) 2 = 3 ⋅ ( 3 ⋅ 3 ) 2 = 243
5 7 5^7 5 7
5 7 = 5 ⋅ ( 5 3 ) 2 = 5 ⋅ ( 5 ⋅ ( 5 ) 2 ) 2 = 78125 5^7=5\cdot(5^3)^2=5\cdot(5\cdot(5)^2)^2=78125 5 7 = 5 ⋅ ( 5 3 ) 2 = 5 ⋅ ( 5 ⋅ ( 5 ) 2 ) 2 = 78125
5.15(4.15) 用算法EXP代替算法EXPREC计算5.14
2 5 2^5 2 5
5 = 101 B 5=101B 5 = 101 B
初始时y=1
第一次循环j=2:y = y 2 = 1 , d 2 = 1 → y = x y = 2 y=y^2=1,d_2=1\rightarrow y=xy=2 y = y 2 = 1 , d 2 = 1 → y = x y = 2
第二次循环j=1:y = y 2 = 4 , d 1 = 0 y=y^2=4,d_1=0 y = y 2 = 4 , d 1 = 0
第三次循环j=0:y = y 2 = 16 , d 0 = 1 → y = x y = 32 y=y^2=16,d_0=1\rightarrow y=xy=32 y = y 2 = 16 , d 0 = 1 → y = x y = 32
因此2 5 = y = 32 2^5=y=32 2 5 = y = 32
2 7 2^7 2 7
7 = 111 B 7=111B 7 = 111 B
初始时y=1
第一次循环j=2:y = y 2 = 1 , d 2 = 1 → y = x y = 2 y=y^2=1,d_2=1\rightarrow y=xy=2 y = y 2 = 1 , d 2 = 1 → y = x y = 2
第二次循环j=1:y = y 2 = 4 , d 1 = 1 → y = x y = 8 y=y^2=4,d_1=1\rightarrow y=xy=8 y = y 2 = 4 , d 1 = 1 → y = x y = 8
第三次循环j=0:y = y 2 = 64 , d 0 = 1 → y = x y = 128 y=y^2=64,d_0=1\rightarrow y=xy=128 y = y 2 = 64 , d 0 = 1 → y = x y = 128
因此2 7 = y = 128 2^7=y=128 2 7 = y = 128
3 5 3^5 3 5
5 = 101 B 5=101B 5 = 101 B
初始时y=1
第一次循环j=2:y = y 2 = 1 , d 2 = 1 → y = x y = 3 y=y^2=1,d_2=1\rightarrow y=xy=3 y = y 2 = 1 , d 2 = 1 → y = x y = 3
第二次循环j=1:y = y 2 = 9 , d 1 = 0 y=y^2=9,d_1=0 y = y 2 = 9 , d 1 = 0
第三次循环j=0:y = y 2 = 81 , d 0 = 1 → y = x y = 243 y=y^2=81,d_0=1\rightarrow y=xy=243 y = y 2 = 81 , d 0 = 1 → y = x y = 243
因此3 5 = y = 243 3^5=y=243 3 5 = y = 243
5 7 5^7 5 7
7 = 111 B 7=111B 7 = 111 B
初始时y=1
第一次循环j=2:y = y 2 = 1 , d 2 = 1 → y = x y = 5 y=y^2=1,d_2=1\rightarrow y=xy=5 y = y 2 = 1 , d 2 = 1 → y = x y = 5
第二次循环j=1:y = y 2 = 25 , d 1 = 1 → y = x y = 125 y=y^2=25,d_1=1\rightarrow y=xy=125 y = y 2 = 25 , d 1 = 1 → y = x y = 125
第三次循环j=0:y = y 2 = 15625 , d 0 = 1 → y = x y = 78125 y=y^2=15625,d_0=1\rightarrow y=xy=78125 y = y 2 = 15625 , d 0 = 1 → y = x y = 78125
因此5 7 = y = 78125 5^7=y=78125 5 7 = y = 78125
5.29 用图说明算法MAJORITY
对下列数组的运算
5 7 5 4 5
5
7
5
4
5
candidate(1)
candidate(3)
candidate(5)
cnt=1
cnt=0,退出循环
cnt=1
cnt=0,退出循环
j=5,返回5
此时c=5
,count=0
5
7
5
4
5
count=1
count=1
count=2
count=2
count=3
由于c o u n t = 3 > 2 count=3>2 co u n t = 3 > 2 ,返回多数元素c=5
5 7 5 4 8
5
7
5
4
8
candidate(1)
candidate(3)
candidate(5)
cnt=1
cnt=0,退出循环
cnt=1
cnt=0,退出循环
j=5,返回8
此时c=8
,count=0
5
7
5
4
8
count=0
count=0
count=0
count=0
count=1
由于c o u n t = 1 < 2 count=1<2 co u n t = 1 < 2 ,因此不存在多数元素
2 4 1 4 4 4 6 4
2
4
1
4
4
4
6
4
candidate(1)
candidate(3)
candidate(5)
cnt=1
cnt=0,退出循环
cnt=1
cnt=0,退出循环
cnt=1
cnt=2
cnt=1
cnt=2,j=8,退出循环
此时c=4
,count=0
2
4
1
4
4
4
6
4
count=0
count=1
count=1
count=2
count=3
count=4
count=4
count=5
由于c o u n t = 5 > 4 count=5>4 co u n t = 5 > 4 ,返回多数元素c=4
5.31 证明结论对错:如果算法MAJORITY
的过程candidate
的第7步中j=n
但count=0
,那么c
是多数元素
该结论错误。下面给出反例:
对于仅有2个元素的数组A [ ] = { a 1 , a 2 } , a 1 ≠ a 2 A[\ ]=\{a_1,a_2\},a_1\not = a_2 A [ ] = { a 1 , a 2 } , a 1 = a 2 .
执行candidate
算法:
a1
a2
candidate(1)
count=1
count=0
仅进行一次循环,此时j=2=n
且count=0
,c=a2
,显然a2不是多数元素。
5.32 证明结论对错:如果算法MAJORITY
的过程candidate
的第7步中j=n
但count>0
,那么c
是多数元素
该结论错误。下面给出反例:
对于仅有3个元素的数组A [ ] = { a 1 , a 2 , a 3 } , a 1 ≠ a 2 ≠ a 3 A[\ ]=\{a_1,a_2,a_3\},a_1\not = a_2\not =a_3 A [ ] = { a 1 , a 2 , a 3 } , a 1 = a 2 = a 3 .
执行candidate
算法:
a1
a2
a3
candidate(1)
candidate(3)
count=1
count=0
count=1
candidate(3)
中j=n=3
,并未进入循环,此时count=1>0
,c=a3
,显然a3不是多数元素。
第6章 分治
6.5 给出一个整数数组A [ 1.. n ] A[1..n] A [ 1.. n ] 中求出所有元素和的分治算法,此算法应从把输入元素近似的划分为两半开始。算法所需的工作空间是多少?
输入:EleSum(1,n)
输出:A[1…n]的元素和
1 2 3 4 5 6 EleSum(left,right) if left==right return A[left] else mid=(left+right)/2 return EleSum(left,mid)+Elesum(mid+1 ,right)
每次为mid申请O ( 1 ) O(1) O ( 1 ) 的空间,而递归的深度为l o g n logn l o g n ,因此所需空间为Θ ( l o g n ) \Theta(log\ n) Θ ( l o g n )
6.2 考虑算法SLOWMINMAX
,它是将算法MINMAX
的检验条件if high-low=1
修改为if high =low
,并对此算法做一些相应改变而得出的。这样,在算法SLOWMINMAX
中,当输入数组的大小为1时,递归停止。计算由此算法找出数组A [ 1 … n ] A[1…n] A [ 1 … n ] 中的最大值和最小值所需的比较次数,这里n是2的幂。解释此算法的比较次数为什么大于算法MINMAX
的比较次数[提示:在这种情形下,初始条件是C(1)=0
]。
此时元素比较次数的递推式为
C ( n ) = { 0 , n = 1 2 C ( n / 2 ) + 2 , n > 1 C(n)=\begin{cases}0,n=1\\ 2C(n/2)+2,n>1\end{cases}
C ( n ) = { 0 , n = 1 2 C ( n /2 ) + 2 , n > 1
求解此递推式,
C ( n ) = 2 C ( n / 2 ) + 2 = 4 C ( n / 4 ) + 4 + 2 = 8 C ( n / 8 ) + 8 + 4 + 2 = . . . = 2 k C ( n / 2 k ) + 2 k + 2 k − 1 + . . . + 2 = 2 n − 2 \begin{align*}C(n)&=2C(n/2)+2\\&=4C(n/4)+4+2\\&=8C(n/8)+8+4+2\\&=...\\&=2^kC(n/2^k)+2^k+2^{k-1}+...+2\\&=2n-2\end{align*}
C ( n ) = 2 C ( n /2 ) + 2 = 4 C ( n /4 ) + 4 + 2 = 8 C ( n /8 ) + 8 + 4 + 2 = ... = 2 k C ( n / 2 k ) + 2 k + 2 k − 1 + ... + 2 = 2 n − 2
显然此时元素比较次数2n-2大于3n/2-2
因为此算法的递归终止条件和MINMAX
不同,递归深度更大
6.10 用算法MERGESORT
进行排序
32 15 14 15 11 17 25 51 32\quad15\quad14\quad15\quad11\quad17\quad25\quad51 32 15 14 15 11 17 25 51
[ 15 32 ] [ 14 15 ] [ 11 17 ] [ 25 51 ] ↓ [ 14 15 15 32 ] [ 11 17 25 51 ] ↓ [ 11 14 15 15 17 25 32 51 ] [15\ 32]\quad[14\ 15]\quad[11\ 17]\quad[25\ 51] \\ \downarrow\\ [14\ 15\ 15\ 32]\quad[11\ 17\ 25\ 51]\\ \downarrow \\ [11\ 14\ 15\ 15\ 17\ 25\ 32\ 51]
[ 15 32 ] [ 14 15 ] [ 11 17 ] [ 25 51 ] ↓ [ 14 15 15 32 ] [ 11 17 25 51 ] ↓ [ 11 14 15 15 17 25 32 51 ]
12 25 17 19 51 32 45 18 22 37 15 12\quad25\quad17\quad19\quad51\quad32\quad45\quad18\quad22\quad37\quad15 12 25 17 19 51 32 45 18 22 37 15
[ 12 ] [ 25 ] [ 17 ] [ 19 ] [ 51 ] [ 32 ] [ 45 ] [ 18 ] [ 22 ] [ 37 ] [ 15 ] ↓ [ 12 25 ] [ 17 ] [ 19 51 ] [ 32 ] [ 45 18 ] [ 22 ] [ 37 15 ] ↓ [ 12 25 ] [ 17 19 51 ] [ 18 32 45 ] [ 15 22 37 ] ↓ [ 12 17 19 25 51 ] [ 15 18 22 32 37 45 ] ↓ [ 12 15 17 18 19 22 25 32 37 45 51 ] [12]\quad[25]\quad[17]\quad[19]\quad[51]\quad[32]\quad[45]\quad[18]\quad[22]\quad[37]\quad[15]\\\downarrow\\ [12\ 25]\quad[17]\quad[19\ 51]\quad[32]\quad[45\ 18]\quad[22]\quad[37\ 15]\\\downarrow\\ [12\ 25]\quad[17\ 19\ 51]\quad[18\ 32\ 45]\quad[15\ 22\ 37]\\\downarrow\\ [12\ 17\ 19\ 25\ 51]\quad[15\ 18\ 22\ 32\ 37\ 45]\\\downarrow\\ [12\ 15\ 17\ 18\ 19\ 22\ 25\ 32\ 37\ 45\ 51]
[ 12 ] [ 25 ] [ 17 ] [ 19 ] [ 51 ] [ 32 ] [ 45 ] [ 18 ] [ 22 ] [ 37 ] [ 15 ] ↓ [ 12 25 ] [ 17 ] [ 19 51 ] [ 32 ] [ 45 18 ] [ 22 ] [ 37 15 ] ↓ [ 12 25 ] [ 17 19 51 ] [ 18 32 45 ] [ 15 22 37 ] ↓ [ 12 17 19 25 51 ] [ 15 18 22 32 37 45 ] ↓ [ 12 15 17 18 19 22 25 32 37 45 51 ]
6.13 列出一组数据,使其满足以下条件
BOTTOMUPSORT
和MERGESORT
执行相同的元素比较次数
数据:A [ 1.. n ] = [ 8 , 7 , 2 , 1 , 6 , 5 , 4 , 3 ] A[1..n]=[8,7,2,1,6,5,4,3] A [ 1.. n ] = [ 8 , 7 , 2 , 1 , 6 , 5 , 4 , 3 ]
当n = 2 k n=2^k n = 2 k 时,两种算法的递归树均一致,比较次数也一致
BOTTOMUPSORT
执行的元素比较次数大于MERGESORT
数据:A [ 1..6 ] = { 1 , 2 , 3 , 4 , 5 , 6 } A[1..6]=\{1,2,3,4,5,6\} A [ 1..6 ] = { 1 , 2 , 3 , 4 , 5 , 6 }
[ 1 2 3 4 5 6 ] ↓ [ 1 2 3 4 ] [ 5 6 ] ↓ [ 1 2 ] [ 3 4 ] [ 5 6 ] ↓ 1 2 3 4 5 6 [1\ 2 \ 3\ 4\ 5\ 6]\\\downarrow \\ [1\ 2\ 3\ 4]\quad [5\ 6]\\\downarrow\\ [1\ 2\ ]\quad [3\ 4]\quad [5\ 6]\\\downarrow\\ 1\quad 2\quad3\quad 4\quad 5\quad 6
[ 1 2 3 4 5 6 ] ↓ [ 1 2 3 4 ] [ 5 6 ] ↓ [ 1 2 ] [ 3 4 ] [ 5 6 ] ↓ 1 2 3 4 5 6
BOTTOMUPSORT执行比较次数为3+2+4=9次
1 2 3 4 5 6 ↓ [ 1 ] [ 2 3 ] [ 4 ] [ 5 6 ] ↓ [ 1 2 3 ] [ 4 5 6 ] ↓ [ 1 2 3 4 5 6 ] 1\quad 2\quad 3\quad 4\quad\ 5\quad 6\\\downarrow \\ [1]\quad[2\ 3]\quad [4]\quad [5\ 6]\\ \downarrow\\ [1\ 2\ 3]\quad [4\ 5\ 6]\\\downarrow\\ [1\ 2\ 3\ 4\ 5\ 6]
1 2 3 4 5 6 ↓ [ 1 ] [ 2 3 ] [ 4 ] [ 5 6 ] ↓ [ 1 2 3 ] [ 4 5 6 ] ↓ [ 1 2 3 4 5 6 ]
MERGESORT执行比较次数为2+2+3=7次
BOTTOMUPSORT
执行的元素比较次数小于MERGESORT
数据:A [ 1..5 ] = { 5 , 4 , 3 , 2 , 1 } A[1..5]=\{5,4,3,2,1\} A [ 1..5 ] = { 5 , 4 , 3 , 2 , 1 }
BOTTOMUPSORT执行比较次数为2+2+1=5次
MERGESORT执行比较次数为2+2+3=7次
6.17 用SELECT
在例6.1的数据中找出第k
小元素
A [ ] = { 8 , 33 , 17 , 51 , 57 , 49 , 35 , 11 , 25 , 37 , 14 , 3 , 2 , 13 , 52 , 12 , 6 , 29 , 32 , 54 , 5 , 16 , 22 , 23 , 7 } A[]=\{8,33,17,51,57,49,35,11,25,37,14,3,2,13,52,12,6,29,32,54,5,16,22,23,7\} A [ ] = { 8 , 33 , 17 , 51 , 57 , 49 , 35 , 11 , 25 , 37 , 14 , 3 , 2 , 13 , 52 , 12 , 6 , 29 , 32 , 54 , 5 , 16 , 22 , 23 , 7 }
阈值为6:即当剩余元素≤6时直接排序并返回A[k]
k=1
划分为5组:
{ 8 , 33 , 17 , 51 , 57 } , { 49 , 35 , 11 , 25 , 37 } , { 14 , 3 , 2 , 13 , 52 } , { 12 , 6 , 29 , 32 , 54 } , { 5 , 16 , 22 , 23 , 7 } \{8,33,17,51,57\},\{49,35,11,25,37\},\{14,3,2,13,52\},\{12,6,29,32,54\},\{5,16,22,23,7\} { 8 , 33 , 17 , 51 , 57 } , { 49 , 35 , 11 , 25 , 37 } , { 14 , 3 , 2 , 13 , 52 } , { 12 , 6 , 29 , 32 , 54 } , { 5 , 16 , 22 , 23 , 7 } 每组升序取中项:{ 33 , 35 , 13 , 29 , 16 } \{33,35,13,29,16\} { 33 , 35 , 13 , 29 , 16 }
递归求中项元素:m m = 29 mm=29 mm = 29
将A划分为3组:
{ 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } \{8,17,11,25,14,3,2,13,12,6,5,16,22,23,7\},\{29\},\{33,51,57,49,35,37,52,32,54\} { 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } 由于1<15=|A1|,递归对A1求解:
划分为3组:{ 8 , 17 , 11 , 25 , 14 } , { 3 , 2 , 13 , 12 , 6 } , { 5 , 16 , 22 , 23 , 7 } \{8,17,11,25,14\},\{3,2,13,12,6\},\{5,16,22,23,7\} { 8 , 17 , 11 , 25 , 14 } , { 3 , 2 , 13 , 12 , 6 } , { 5 , 16 , 22 , 23 , 7 }
每组升序取中项集合:{ 14 , 6 , 16 } \{14,6,16\} { 14 , 6 , 16 } ,m m = 14 mm=14 mm = 14
将A划分为3组:{ 8 , 11 , 3 , 2 , 13 , 12 , 6 , 5 , 7 } , { 14 } , { 17 , 25 , 16 , 22 , 23 } \{8,11,3,2,13,12,6,5,7\},\{14\},\{17,25,16,22,23\} { 8 , 11 , 3 , 2 , 13 , 12 , 6 , 5 , 7 } , { 14 } , { 17 , 25 , 16 , 22 , 23 }
由于1<9=|A1|,递归对A1求解:
划分为1组:{ 8 , 11 , 3 , 2 , 13 } \{8,11,3,2,13\} { 8 , 11 , 3 , 2 , 13 }
升序取中项:mm=8
将A划分为3组:{ 3 , 2 } , { 8 } , { 11 , 13 } \{3,2\},\{8\},\{11,13\} { 3 , 2 } , { 8 } , { 11 , 13 }
由于1<2=|A1|,递归对于A1求解:
只剩2个元素,小于阈值,直接排序求解A[k]=A[1]=2
k=9
根据上问,将A划分为3组:
{ 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } \{8,17,11,25,14,3,2,13,12,6,5,16,22,23,7\},\{29\},\{33,51,57,49,35,37,52,32,54\} { 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } 由于9<15=|A1|,递归对A1求解:
划分为3组:{ 8 , 17 , 11 , 25 , 14 } , { 3 , 2 , 13 , 12 , 6 } , { 5 , 16 , 22 , 23 , 7 } \{8,17,11,25,14\},\{3,2,13,12,6\},\{5,16,22,23,7\} { 8 , 17 , 11 , 25 , 14 } , { 3 , 2 , 13 , 12 , 6 } , { 5 , 16 , 22 , 23 , 7 }
每组升序取中项:{ 14 , 6 , 16 } \{14,6,16\} { 14 , 6 , 16 } ,m m = 14 mm=14 mm = 14
将A划分为3组:{ 8 , 11 , 3 , 2 , 13 , 12 , 6 , 5 , 7 } , { 14 } , { 17 , 25 , 16 , 22 , 23 } \{8,11,3,2,13,12,6,5,7\},\{14\},\{17,25,16,22,23\} { 8 , 11 , 3 , 2 , 13 , 12 , 6 , 5 , 7 } , { 14 } , { 17 , 25 , 16 , 22 , 23 }
由于9=9=|A1|,递归对A1求解:
划分为2组:{ 8 , 11 , 3 , 2 , 13 } , { 12 , 6 , 5 , 7 } \{8,11,3,2,13\},\{12,6,5,7\} { 8 , 11 , 3 , 2 , 13 } , { 12 , 6 , 5 , 7 }
每组升序取中项集合:{ 8 , 6 } \{8,6\} { 8 , 6 } ,mm=6
将A划分为3组:{ 3 , 2 , 5 } , { 6 } , { 8 , 11 , 13 , 12 , 7 } \{3,2,5\},\{6\},\{8,11,13,12,7\} { 3 , 2 , 5 } , { 6 } , { 8 , 11 , 13 , 12 , 7 }
由于k=9>4=|A1|+|A2|
递归求解A3,k=k-|A1|-|A2|=5
由于5<阈值6,直接排序后返回A[5]=13
k=17
根据上问,将A划分为3组:
{ 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } \{8,17,11,25,14,3,2,13,12,6,5,16,22,23,7\},\{29\},\{33,51,57,49,35,37,52,32,54\} { 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } 由于k=17>16=|A1|+|A2|,递归对A3求解,k=k-16=1
将A=A3分为2组:{ 33 , 51 , 57 , 49 , 35 } , { 37 , 52 , 32 , 54 } \{33,51,57,49,35\},\{37,52,32,54\} { 33 , 51 , 57 , 49 , 35 } , { 37 , 52 , 32 , 54 }
取中项集合:{ 49 , 37 } \{49,37\} { 49 , 37 } ,mm=37
划分为3组:{ 33 , 35 , 32 } , { 37 } , { 51 , 57 , 49 , 52 , 54 } \{33,35,32\},\{37\},\{51,57,49,52,54\} { 33 , 35 , 32 } , { 37 } , { 51 , 57 , 49 , 52 , 54 }
由于k=1<3=|A1|,递归对A1进行求解:
由于只剩3个元素,直接排序求解A[k]=32
k=22
根据上问,将A划分为3组:
{ 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } \{8,17,11,25,14,3,2,13,12,6,5,16,22,23,7\},\{29\},\{33,51,57,49,35,37,52,32,54\} { 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } 由于k=22>16=|A1|+|A2|,递归对A3求解,k=k-16=6
将A=A3分为2组:{ 33 , 51 , 57 , 49 , 35 } , { 37 , 52 , 32 , 54 } \{33,51,57,49,35\},\{37,52,32,54\} { 33 , 51 , 57 , 49 , 35 } , { 37 , 52 , 32 , 54 }
取中项集合:{ 49 , 37 } \{49,37\} { 49 , 37 } ,mm=37
划分为3组:{ 33 , 35 , 32 } , { 37 } , { 51 , 57 , 49 , 52 , 54 } \{33,35,32\},\{37\},\{51,57,49,52,54\} { 33 , 35 , 32 } , { 37 } , { 51 , 57 , 49 , 52 , 54 }
由于k=6>4=|A1|+|A2|,递归对A3进行求解,k=k-4=2
由于只剩5个元素,直接排序后求解:A[k]=51
k=25
根据上问,将A划分为3组:
{ 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } \{8,17,11,25,14,3,2,13,12,6,5,16,22,23,7\},\{29\},\{33,51,57,49,35,37,52,32,54\} { 8 , 17 , 11 , 25 , 14 , 3 , 2 , 13 , 12 , 6 , 5 , 16 , 22 , 23 , 7 } , { 29 } , { 33 , 51 , 57 , 49 , 35 , 37 , 52 , 32 , 54 } 由于k=25>16=|A1|+|A2|,递归对A3求解,k=k-16=9
将A=A3分为2组:{ 33 , 51 , 57 , 49 , 35 } , { 37 , 52 , 32 , 54 } \{33,51,57,49,35\},\{37,52,32,54\} { 33 , 51 , 57 , 49 , 35 } , { 37 , 52 , 32 , 54 }
取中项集合:{ 49 , 37 } \{49,37\} { 49 , 37 } ,mm=37
划分为3组:{ 33 , 35 , 32 } , { 37 } , { 51 , 57 , 49 , 52 , 54 } \{33,35,32\},\{37\},\{51,57,49,52,54\} { 33 , 35 , 32 } , { 37 } , { 51 , 57 , 49 , 52 , 54 }
由于k=9>4=|A1|+|A2|,递归对A3进行求解,k=k-4=5
由于只剩5个元素,直接排序后求解:A[k]=57
6.31 对于数组{27,13,31,18,45,16,17,53},应用算法SPLIT进行处理
low=1,high=8,主元为A[1]=27,初始i=low=1
i=1, j=2: 13<27, i=2, j=2 不交换
[ 27 13 31 18 45 16 17 53 ] [27\quad 13\quad 31\quad 18\quad 45\quad 16\quad 17\quad 53] [ 27 13 31 18 45 16 17 53 ]
i=2, j=4: 18<27, i=3, j=4 交换
[ 27 13 18 31 45 16 17 53 ] [27\quad 13\quad 18\quad 31\quad 45\quad 16\quad 17\quad 53] [ 27 13 18 31 45 16 17 53 ]
i=3, j=6: 16<27, i=4, j=6 交换
[ 27 13 18 16 45 31 17 53 ] [27\quad 13\quad 18\quad 16\quad 45\quad 31\quad 17\quad 53] [ 27 13 18 16 45 31 17 53 ]
i=4, j=7: 17<27, i=5, j=7 交换
[ 27 13 18 16 17 31 45 53 ] [27\quad 13\quad 18\quad 16\quad 17\quad 31\quad 45\quad 53] [ 27 13 18 16 17 31 45 53 ]
结束后互换A[1]和A[5]
最终结果:[ 17 13 18 16 27 31 45 53 ] [17\quad 13\quad 18\quad 16\quad 27\quad 31\quad 45\quad 53] [ 17 13 18 16 27 31 45 53 ]
6.32 对于算法SPLIT
,当算法以输入数组A [ 1.. n ] A[1..n] A [ 1.. n ] 表示且不包括A[low]和A[i]的交换时,执行的元素比较次数设为f ( n ) f(n) f ( n )
对于什么样的A [ 1.. n ] A[1..n] A [ 1.. n ] ,有f ( n ) = 0 f(n)=0 f ( n ) = 0
首先,当a 2.. n > a 1 a_{2..n}> a_1 a 2.. n > a 1 时,不会发生元素交换;
而当i==j
时也不会发生元素交换,也就是说存在下标k,
A [ 1.. n ] = a 1 , a 2 , . . . , a k , a k + 1 , . . . , a n A[1..n]={a_1,a_2,...,a_k,a_{k+1},...,a_n}
A [ 1.. n ] = a 1 , a 2 , ... , a k , a k + 1 , ... , a n
a 2 a2 a 2 到a k a_k a k 均≤ a 1 \le a_1 ≤ a 1 ,a k + 1 a_{k+1} a k + 1 到a n a_n a n 均> a 1 >a_1 > a 1
f ( n ) f(n) f ( n ) 最大值是什么,解释什么时候达到最大值
m a x ( f ( n ) ) max(f(n)) ma x ( f ( n )) =数组中不大于a 1 a_1 a 1 的元素个数,当a 2 > a 1 a_2>a_1 a 2 > a 1 时有最大值
6.36 用QUICKSORT对数组排序
{ 24 , 33 , 24 , 45 , 12 , 12 , 24 , 12 } \{24,33,24,45,12,12,24,12\} { 24 , 33 , 24 , 45 , 12 , 12 , 24 , 12 }
[ 12 , 24 , 12 , 12 , 24 ] [ 24 ] [ 33 , 45 ] ↓ [ 12 , 12 ] [ 12 ] [ 24 , 24 ] [ 24 ] [ 33 ] [ 45 ] ↓ [ 12 ] [ 12 ] [ 12 ] [ 24 ] [ 24 ] [ 24 ] [ 33 ] [ 45 ] [12,24,12,12,24]\ [24]\ [33,45] \\ \downarrow\\
[12,12]\ [12]\ [24,24]\ [24]\ [33]\ [45]\\ \downarrow\\
[12]\ [12]\ [12]\ [24]\ [24]\ [24]\ [33]\ [45]
[ 12 , 24 , 12 , 12 , 24 ] [ 24 ] [ 33 , 45 ] ↓ [ 12 , 12 ] [ 12 ] [ 24 , 24 ] [ 24 ] [ 33 ] [ 45 ] ↓ [ 12 ] [ 12 ] [ 12 ] [ 24 ] [ 24 ] [ 24 ] [ 33 ] [ 45 ]
{ 3 , 4 , 5 , 6 , 7 } \{3,4,5,6,7\} { 3 , 4 , 5 , 6 , 7 }
[ 3 ] [ 4 , 5 , 6 , 7 ] ↓ [ 3 ] [ 4 ] [ 5 , 6 , 7 ] ↓ . . . ↓ [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [3]\ [4,5,6,7]\\ \downarrow\\
[3]\ [4]\ [5,6,7]\\ \downarrow\\
...\\ \downarrow\\
[3]\ [4]\ [5]\ [6]\ [7]
[ 3 ] [ 4 , 5 , 6 , 7 ] ↓ [ 3 ] [ 4 ] [ 5 , 6 , 7 ] ↓ ... ↓ [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ]
{ 23 , 32 , 27 , 18 , 45 , 11 , 63 , 12 , 19 , 16 , 25 , 52 , 14 } \{23,32,27,18,45,11,63,12,19,16,25,52,14\} { 23 , 32 , 27 , 18 , 45 , 11 , 63 , 12 , 19 , 16 , 25 , 52 , 14 }
[ 14 , 18 , 11 , 12 , 19 , 16 ] [ 23 ] [ 32 , 27 , 45 , 63 , 25 , 52 ] ↓ [ 12 , 11 ] [ 14 ] [ 18 , 19 , 16 ] [ 23 ] [ 25 , 27 ] [ 32 ] [ 45 , 63 , 52 ] ↓ [ 11 ] [ 12 ] [ 14 ] [ 16 ] [ 18 ] [ 19 ] [ 23 ] [ 25 ] [ 27 ] [ 32 ] [ 45 ] [ 52 ] [ 63 ] [14,18,11,12,19,16]\ [23]\ [32,27,45,63,25,52]\\ \downarrow\\
[12,11]\ [14]\ [18,19,16]\ [23]\ [25,27]\ [32]\ [45,63,52]\\ \downarrow\\
[11]\ [12]\ [14]\ [16]\ [18]\ [19]\ [23]\ [25]\ [27]\ [32]\ [45]\ [52]\ [63]
[ 14 , 18 , 11 , 12 , 19 , 16 ] [ 23 ] [ 32 , 27 , 45 , 63 , 25 , 52 ] ↓ [ 12 , 11 ] [ 14 ] [ 18 , 19 , 16 ] [ 23 ] [ 25 , 27 ] [ 32 ] [ 45 , 63 , 52 ] ↓ [ 11 ] [ 12 ] [ 14 ] [ 16 ] [ 18 ] [ 19 ] [ 23 ] [ 25 ] [ 27 ] [ 32 ] [ 45 ] [ 52 ] [ 63 ]
6.45 写出传统的矩阵乘法算法
1 2 3 4 5 6 MatrixMulti(A[n][n],B[n][n]): for i=1 to n: for j=1 to n: for k=1 to n: C[i][j]= C[i][j]+A[i][k]*B[k][j] return C[n][n]
6.50 设计分治算法判断两个二叉树T 1 T_1 T 1 和T 2 T_2 T 2 是否等同
如果T 1 = T 2 T_1=T_2 T 1 = T 2 ,则T 1 . d a t a = T 2 . d a t a 、 T 1 . l c h i l d = T 2. l c h i l d 、 T 1 . r c h i l d = T 2 . r c h i l d T_1.data=T_2.data、T_1.lchild=T2.lchild、T_1.rchild=T_2.rchild T 1 . d a t a = T 2 . d a t a 、 T 1 . l c hi l d = T 2. l c hi l d 、 T 1 . rc hi l d = T 2 . rc hi l d
因此我们可以递归判断根节点值和左右子树是否相同
有3种情况:
两个根节点同时为空
此时返回True即可
两个根节点都不为空
此时判断值是否相同,且分别递归判断节点1和节点2的左/右子树是否相同
一个为空、另一个不为空
此时返回False即可
1 2 3 4 5 6 7 8 isBiTreeEqual(root1,root2) if (root1==NULL and root2!=NULL or root1!=NULL and root2==NULL) return False else if (root1!=NULL and root2!=NULL) return root1.data==root2.data and isBiTreeEqual(root1.left,root2.left) and isBiTreeEqual(root1.right,root2.right) else return True
第7章 动态规划
7.5 用算法LCS找出A="xzyzzyx"和B="zxyyzxz"的最长公共子序列的长度,给出一个最长公共子序列
A
x
z
y
z
z
y
x
B
0
0
0
0
0
0
0
z
0
0
1
1
1
1
1
1
x
0
1
1
1
1
1
1
2
y
0
1
1
2
2
2
2
2
y
0
1
1
2
2
2
3
3
z
0
1
2
2
3
3
3
3
x
0
1
2
2
3
3
3
4
z
0
1
2
2
3
4
4
4
长度为4,一个最长公共子序列:“xzzx”
7.6 说明如何修改算法LCS,使得它输出最长公共子序列
我们可以通过从f [ n ] [ m ] f[n][m] f [ n ] [ m ] 逆向查找,找到其更新来源,就能找出所有的最长公共子序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ans=set () findLCS(i,j,str ): while (i>0 and j>0 ) if (a[i]==b[j]) str =str +a[i-1 ] i=i-1 j=j-1 else if (f[i-1 ][j]>f[i][j-1 ]) i=i-1 else if (f[i-1 ][j]<f[i][j-1 ]) j=j-1 else findLCS(i-1 ,j,str ) findLCS(i,j-1 ,str ) return ans.insert(str .reverse())
该算法中ans是存储最长公共子序列的集合
转移种类有:
a [ i ] = b [ j ] a[i]=b[j] a [ i ] = b [ j ] ,则一定可以作为一个字符存进str中
a [ i ] ≠ b [ j ] a n d f [ i − 1 ] [ j ] > f [ i ] [ j − 1 ] a[i]\not =b[j]\ and\ f[i-1][j]>f[i][j-1] a [ i ] = b [ j ] an d f [ i − 1 ] [ j ] > f [ i ] [ j − 1 ] ,则从f [ i − 1 ] [ j ] f[i-1][j] f [ i − 1 ] [ j ] 转移而来
当小于号同理
如果两个相等,则说明可以从两边转移而来,因此需要有两个递归分支
7.7 如何修改算法LCS,使得它仅需要Θ ( m i n { m , n } ) \Theta (min\{m,n\}) Θ ( min { m , n }) 的空间
由于每个状态f [ i ] [ j ] f[i][j] f [ i ] [ j ] 的更新仅与f [ i − 1 ] [ j − 1 ] 、 f [ i ] [ j − 1 ] 、 f [ i − 1 ] [ j ] f[i-1][j-1]、f[i][j-1]、f[i-1][j] f [ i − 1 ] [ j − 1 ] 、 f [ i ] [ j − 1 ] 、 f [ i − 1 ] [ j ] 有关,我们可以采用滚动数组实现LCS,这里不妨假定1 ≤ i ≤ n , 1 ≤ j ≤ m , m ≤ n 1\le i\le n,1\le j\le m,m\le n 1 ≤ i ≤ n , 1 ≤ j ≤ m , m ≤ n ,即只保留f [ i ] 、 f [ i − 1 ] f[i]、f[i-1] f [ i ] 、 f [ i − 1 ] 的值
1 2 3 4 5 6 7 f[2 ][m]for (int i=1 ;i<=n;i++) for (int j=1 ;j<=m;j++) if (a[i]==b[j]) f[i%2 ][j]=f[(i-1 )%2 ][j-1 ]+1 ; else f[i%2 ][j]=max (f[(i-1 )%2 ][j],f[i%2 ][j-1 ])
n ≤ m n\le m n ≤ m 时同理,这样空间复杂度为2 m = Θ ( m i n { m , n } ) 2m=\Theta(min\{m,n\}) 2 m = Θ ( min { m , n })
7.9 用MATCHAIN计算矩阵相乘后如图所示,找出C [ 1 , 5 ] C[1,5] C [ 1 , 5 ] 和执行乘法运算M 1 × . . . × M 5 M_1\times ...\times M_5 M 1 × ... × M 5 的最优括号表达式
C [ 1 , 5 ] = m i n { C [ 1 , 1 ] + C [ 2 , 5 ] + 4 × 5 × 5 = 307 C [ 1 , 2 ] + C [ 3 , 5 ] + 4 × 3 × 5 = 252 C [ 1 , 3 ] + C [ 4 , 5 ] + 4 × 6 × 5 = 372 C [ 1 , 4 ] + C [ 5 , 5 ] + 4 × 4 × 5 = 260 = 252 C[1,5]=min
\begin{cases}
C[1,1]+C[2,5]+4\times5\times5=307 \\
C[1,2]+C[3,5]+4\times3\times5=252 \\
C[1,3]+C[4,5]+4\times6\times5=372 \\
C[1,4]+C[5,5]+4\times4\times5=260 \\
\end{cases}
=252
C [ 1 , 5 ] = min ⎩ ⎨ ⎧ C [ 1 , 1 ] + C [ 2 , 5 ] + 4 × 5 × 5 = 307 C [ 1 , 2 ] + C [ 3 , 5 ] + 4 × 3 × 5 = 252 C [ 1 , 3 ] + C [ 4 , 5 ] + 4 × 6 × 5 = 372 C [ 1 , 4 ] + C [ 5 , 5 ] + 4 × 4 × 5 = 260 = 252
最优表达式为( M 1 × M 2 ) × ( ( M 3 × M 4 ) × M 5 ) (M_1\times M_2)\times ((M_3\times M_4) \times M_5) ( M 1 × M 2 ) × (( M 3 × M 4 ) × M 5 )
7.12 给出三个矩阵的例子,它们的一种乘法顺序需要的数量乘法的次数至少是另一种顺序的100倍
矩阵如下:
M 1 : 100 × 1 M 2 : 1 × 100 M 3 : 100 × 1 M_1:100\times 1\ \ \ \ \ M_2:1\times 100\ \ \ \ \ M_3:100\times 1
M 1 : 100 × 1 M 2 : 1 × 100 M 3 : 100 × 1
顺序1:( M 1 × M 2 ) × M 3 = 100 × 1 × 100 + 100 × 100 × 1 = 20000 (M_1\times M_2)\times M_3=100\times 1\times 100+100\times 100\times 1=20000 ( M 1 × M 2 ) × M 3 = 100 × 1 × 100 + 100 × 100 × 1 = 20000
顺序2:M 1 × ( M 2 × M 3 ) = 1 × 100 × 1 + 100 × 1 × 1 = 200 M_1\times (M_2 \times M_3)=1\times 100\times 1+100\times 1\times 1=200 M 1 × ( M 2 × M 3 ) = 1 × 100 × 1 + 100 × 1 × 1 = 200
因此顺序1的数量乘法次数是顺序2的100倍
7.21 求解背包问题:有4个体积是[2,3,5,6],价值为[3,4,5,7]的物品,背包容量是11
d p [ i , j ] dp[i,j] d p [ i , j ] 如下,其中1 ≤ i ≤ 4 , 1 ≤ j ≤ 11 1\le i\le 4,1\le j\le 11 1 ≤ i ≤ 4 , 1 ≤ j ≤ 11 ,d p [ i , j ] dp[i,j] d p [ i , j ] 表示背包容量为j j j 时,在前i i i 个物品中选取物品的最大价值。
i\j
1
2
3
4
5
6
7
8
9
10
11
1
0
3
3
3
3
3
3
3
3
3
3
2
0
3
4
4
7
7
7
7
7
7
7
3
0
3
4
4
7
7
8
9
9
12
12
4
0
3
4
4
7
7
8
10
11
12
14
因此最大价值为14,选取的物品为1、2、 4
7.22 求解背包问题:有5个体积是[3,5,7,8,9],价值为[4,6,7,9,10]的物品,背包容量是22
d p [ i , j ] dp[i,j] d p [ i , j ] 如下,其中1 ≤ i ≤ 5 , 1 ≤ j ≤ 22 1\le i\le 5,1\le j\le 22 1 ≤ i ≤ 5 , 1 ≤ j ≤ 22 ,d p [ i , j ] dp[i,j] d p [ i , j ] 表示背包容量为j j j 时,在前i i i 个物品中选取物品的最大价值。
i/j
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
0
0
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
4
2
0
0
4
4
6
6
6
10
10
10
10
10
10
10
10
10
10
10
10
10
10
10
3
0
0
4
4
6
6
7
10
10
11
11
13
13
13
17
17
17
17
17
17
17
17
4
0
0
4
4
6
6
7
10
10
11
13
13
15
15
17
19
19
20
20
22
22
22
5
0
0
4
4
6
6
7
10
10
11
13
14
15
16
17
19
20
20
21
23
23
25
因此最大价值为25,选取的物品为2、4、5
7.24 说明如何修改算法KNAPSACK
,使其只需Θ ( C ) \Theta(C) Θ ( C ) 空间,C C C 是背包容量
由于dp[i][j]
中的i
只和i-1
有关,我们可以采用滚动数组的方式实现,此时对于背包容量j
的遍历需要从大到小,否则会修改i-1
次循环时存储的dp
值。
1 2 3 4 5 6 7 8 dp[C] size[N] value[N]for i=1 to n: for j=C to 1 : if (j>=size[i]) dp[j]=max (dp[j],dp[j-size[i]]+value[i])return dp[C]
第8章 贪心算法
8.12 给出一个具有最少顶点的图,证明此贪心算法求解s到t的距离不总是正确的。贪心算法:从s开始,到最近的顶点,称为x;从x出发,到最近的顶点,称为y,最终重复该做法到达t
graph LR
s-->|1|x
x-->|3|t;
s-->|3|t;
如图所示,采用此贪心算法得到s->x->t的距离为4,而s到t的距离为3
8.14 DIJKSTRA
算法是最优的吗?请解释
对于任意两点间距离均不为负的情况,是最优的。
DIJKSTRA
算法基于贪心的思想,实现了全局最优。因为每次取出了未访问结点中距离最小的结点加入已访问结点中,再用该结点更新其他未访问结点的距离,此时被更新的未访问节点距离肯定是起点能通过已访问节点到达该节点的最短距离,如此一直更新距离直到访问完所有节点。
8.23 对图8.8中所示的无向图应用算法KRUSKAL
找出最小耗费生成树,给出所得结果
已选取的节点集合S S S ,已选取的边数量c n t cnt c n t ,最小生成树权值和a n s ans an s
首先对边权从小到大排序
边权-(端点,端点)
S o r t e d − E d g e s : Sorted-Edges: S or t e d − E d g es : [1-(1,2)、2-(1,4)、2-(2,4)、3-(3,6)、3-(5,6)、4-(3,5)、6-(1,3)、6-(4,6)、7-(2,3)、7-(4,5)、9-(3,4)]
从小到大遍历排序后的边,决定是否选取该边
如果该边的两个端点不在同一集合中就可选取,当∣ S ∣ = n |S|=n ∣ S ∣ = n 且c n t = n − 1 cnt=n-1 c n t = n − 1 时退出遍历
1:选取,S = { 1 , 2 } , c n t = 1 , a n s = 1 S=\{1,2\},cnt=1,ans=1 S = { 1 , 2 } , c n t = 1 , an s = 1
2:选取,S = { 1 , 2 , 4 } , c n t = 2 , a n s = 3 S=\{1,2,4\},cnt=2,ans=3 S = { 1 , 2 , 4 } , c n t = 2 , an s = 3
2:不选取
3:选取,S = { 1 , 2 , 3 , 4 , 6 } , c n t = 3 , a n s = 6 S=\{1,2,3,4,6\},cnt=3,ans=6 S = { 1 , 2 , 3 , 4 , 6 } , c n t = 3 , an s = 6
3:选取,S = { 1 , 2 , 3 , 4 , 5 , 6 } , c n t = 4 , a n s = 9 S=\{1,2,3,4,5,6\},cnt=4,ans=9 S = { 1 , 2 , 3 , 4 , 5 , 6 } , c n t = 4 , an s = 9
4:不选取
6:选取,S = { 1 , 2 , 3 , 4 , 5 , 6 } , c n t = 5 , a n s = 15 S=\{1,2,3,4,5,6\},cnt=5,ans=15 S = { 1 , 2 , 3 , 4 , 5 , 6 } , c n t = 5 , an s = 15 ,此时退出循环
最小耗费为15,选取的边为1-2、1-4、1-3、3-6、5-6
8.26 设e e e 是无向图G G G 中一条有最小权重的边,证明e e e 属于G G G 的某个最小耗费生成树
用反证法:
设e e e 的两个端点为v s , v t v_s,v_t v s , v t ,则v s , v t ∈ v ( G ) v_s,v_t\in v(G) v s , v t ∈ v ( G )
假设e e e 不属于G G G 的任何最小耗费生成树,对于∀ M S T ⊆ G \forall MST \subseteq G ∀ MST ⊆ G ,有v ( M S T ) = v ( G ) , ∣ e ( M S T ) ∣ = ∣ v ( G ) ∣ − 1 v(MST)=v(G),|e(MST)|=|v(G)|-1 v ( MST ) = v ( G ) , ∣ e ( MST ) ∣ = ∣ v ( G ) ∣ − 1
则v s , v t ∈ V ( M S T ) v_s,v_t\in V(MST) v s , v t ∈ V ( MST ) ,假设v s , v t v_s,v_t v s , v t 在M S T MST MST 中已存在路径v s v 1 . . . v k v t v_sv_{1}...v_kv_t v s v 1 ... v k v t
现在我们将M S T MST MST 加入边e e e ,显然存在环路C = v s v 1 . . . v k v t + v t v s C=v_sv_1...v_kv_t+v_tv_s C = v s v 1 ... v k v t + v t v s ,并且w ( v t v s ) < w ( v s v 1 . . . v k v t ) w(v_tv_s)<w(v_sv_1...v_kv_t) w ( v t v s ) < w ( v s v 1 ... v k v t )
因此我们可以删除原路径v s v 1 . . . v k v t v_sv_1...v_kv_t v s v 1 ... v k v t 得到耗费更小的M S T 1 MST_1 MS T 1 ,显然这与M S T MST MST 是G G G 的最小耗费生成树冲突。
因此e e e 属于G G G 的某个最小耗费生成树
8.2 5.7节中描述的MAJORITY
是贪心算法吗?请解释
MANORITY
不是贪心算法,因为在candidate()
函数中没有寻找局部最优解的迭代过程。
13.3 考虑13.2节中介绍的3着色算法,试解释如何在算法执行的整个过程中能有效的检验当前向量是否是部分的
假设当前向量为( c 1 , c 2 , c 3 , . . . c m ) (c_1,c_2,c_3,...c_m) ( c 1 , c 2 , c 3 , ... c m ) ,且c 1 c_1 c 1 到c m c_m c m 均被着色,可以遍历每一个可能的组合判断其是否冲突
1 2 3 4 5 6 7 8 for i=1 to m-1 : for j=i+1 to m: if ( connect(i,j)==True and ci==cj) return False endif endfor endforreturn True
如果点i i i 和点j j j 互相邻接且c i c_i c i 等于c j c_j c j ,则不是部分向量
13.4 给出一个8皇后问题的递归算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Queen[8 ][8 ] ans=0 solve8queen(row): if row>8 ans+=1 print_queen() return for column=1 to 8 : if NoConflict(row,column)==True : Queen[row][column]=1 solve8queen(row+1 ) Queen[row][column]=0 NoConflict(row,column): for i=1 to 8 : if Queen[i][column]==1 : return False for i=1 to 8 : j1=column-row+i if (j1<=8 and j1>=1 and Queen[i][j1]==1 ) return False j2=column-i+row if (j2<=8 and j2>=1 and Queen[i][j2]==1 ) return False return True solve8queen(1 )return ans