算法导论学习笔记[0] #20210706


lec 1

Lecture 1
Administrivia; Introduction; Analysis of Algorithms, Insertion Sort, Mergesort

Why study algorithms and performance?

Q0: 如何理解"Performance is the currency of computing."
A0: 实际中常常牺牲性能以获取其它方面的优点,即做"trade-off". 例如为了面向对象等等,我们使用Java而不使用C(即使C更快)。

Q1: 举例说明"Performance often draws the line between what is feasible and what is impossible."
A1: 离散傅里叶变换(DFT)的复杂度是 O ( N 2 ) O(N^2) O(N2),这在历史上曾经一度成为信号处理、物理等领域发展的瓶颈。
1965年,快速傅里叶变换(FFT)被发明,其复杂度仅为 O ( N l o g N ) O(NlogN) O(NlogN),大大推动了信号处理领域的发展。

插入排序(Insertion sort)与其渐近分析

Q0: 对于插入排序的伪代码

for j <- 2 to n
    key <- A[j]
    i <- j - 1
    while i > 0 and {}
        A[i+1] <- A[i]
        i <- i-1
    A[i+1] <- key

请在{}中填写适当的判断条件,使得输出是递增的数列。
A0: A[i] > key
注:如果写成了<,那么将得到递减的数列。

Q1: 接上,填写A[i] > keyA[i] >= key有何区别?
A1: 后者的开销恒大于前者,且会使得排序不稳定。

Q2: 分析算法时我们最常考察Worst-case,有时考察Average-case. 请提出一种新的合理的评判标准。
A2: 例如:算法以 1 − ϵ 1-\epsilon 1ϵ概率在多少时间内运行完。(言之成理即可)

Q3: " T ( n ) T(n) T(n) (the expected time of algorithm of size n n n) is the average time over all inputs of size n n n."有何不准确之处?
A3: 需要对输入的统计分布做出假设。(实际中,可能是加权平均,而不是简单的求平均)

Q4: 在渐近分析中,常数有可能有什么实际意义?
A4: 不同设备的性能、不同运算(如乘法和加法)的开销、不同优化等级,等等。

Q5: 解释记号 ∑ j = 1 n Θ ( j 2 ) = Θ ( n 3 ) \sum_{j=1}^n\Theta(j^2)=\Theta(n^3) j=1nΘ(j2)=Θ(n3).
A5: 如果对于一切 n ∈ N + , j = 1 , ⋯   , n n\in \mathbb N_+,j=1,\cdots,n nN+,j=1,,n,有 m j 2 ≤ a n , j ≤ M j 2 mj^2\le a_{n,j}\le M j^2 mj2an,jMj2一致成立(即 m m m M M M是相同的),则 ∑ j = 1 n a n , j = Θ ( n 3 ) \sum_{j=1}^na_{n,j}=\Theta(n^3) j=1nan,j=Θ(n3).
注:其实 Θ \Theta Θ记号本身就要求了一致性。这里的 ∑ Θ \sum\Theta Θ只不过把这种一致性的要求扩展到关于两个变量。

Q6: 利用Q5的记号分析插入排序。
A6:
Worst case: ∑ j = 2 n Θ ( j ) = Θ ( n 2 ) \sum_{j=2}^n\Theta(j)=\Theta(n^2) j=2nΘ(j)=Θ(n2)
Average case: ∑ j = 2 n Θ ( j / 2 ) = Θ ( n 2 ) \sum_{j=2}^n\Theta(j/2)=\Theta(n^2) j=2nΘ(j/2)=Θ(n2)(当然也可以写 ∑ j = 2 n Θ ( j ) = Θ ( n 2 ) \sum_{j=2}^n\Theta(j)=\Theta(n^2) j=2nΘ(j)=Θ(n2)

归并排序(Merge sort)与其渐近分析

Q0: 从 T ( n ) = Θ ( 1 ) + 2 T ( n / 2 ) + Θ ( n ) T(n)=\Theta(1)+2T(n/2)+\Theta(n) T(n)=Θ(1)+2T(n/2)+Θ(n)这一形式上的表达式,你能回想起归并排序的步骤吗?
A0: 第一项 Θ ( 1 ) \Theta(1) Θ(1)是递归出口:如果 n = 1 n=1 n=1,则直接完成。第二项 2 T ( n / 2 ) 2T(n/2) 2T(n/2)是对数组的前半部分和后半部分分别(递归地)运用归并排序(这里略去了取整等细节,之后能证明这是没有影响的)。第三项是归并过程。

Q1: 简述递归树(Recursion tree)方法如何形式上对 T ( n ) = 2 T ( n / 2 ) + c n T(n)=2T(n/2)+cn T(n)=2T(n/2)+cn作渐近分析。
A1:

cn
T(n/2)
T(n/2)
cn
cn/2
cn/2
T(n/4)
T(n/4)
T(n/4)
T(n/4)

以此类推构造树。无论是哪棵树中,所有结点之和都是 T ( n ) T(n) T(n),也就是 T ( n ) = c n + 2 T ( n / 2 ) = c n + 2 ( c n / 2 ) + 4 T ( n / 4 ) = ⋯ T(n)=cn+2T(n/2)=cn+2(cn/2)+4T(n/4)=\cdots T(n)=cn+2T(n/2)=cn+2(cn/2)+4T(n/4)=.
由于树最终有 l o g n logn logn层(忽略取整等问题),每层各结点之和都是 c n cn cn,故 T ( n ) = Θ ( n l o g n ) T(n)=\Theta(nlogn) T(n)=Θ(nlogn).
注:递归树方法中的“树”结构对于渐近分析本身来说,并不是必要的。比如你可以画这样的链:

cn
2T(n/2)
cn
2·cn/2
4T(n/4)

以此类推下去,最终整条链有 l o g n logn logn个结点,每个结点都代表了 c n cn cn,结果仍是 Θ ( n l o g n ) \Theta(nlogn) Θ(nlogn). 但是,树结构能够一定程度上反映程序运行的机理和过程。例如对二叉树的遍历在一定程度上能反映归并排序运行的机制。

Q2: 对于光滑函数 T ( x ) , x > 0 T(x),x>0 T(x),x>0,严格求解函数方程 T ( x ) = m T ( x / m ) + x l o g m , ∀ m ∈ N + , T ( 1 ) = 1 T(x)=mT(x/m)+xlogm,\forall m\in \mathbb N_+,T(1)=1 T(x)=mT(x/m)+xlogm,mN+,T(1)=1,并证明或否定若光滑函数 U ( x ) , x > 0 U(x),x>0 U(x),x>0满足 U ( x ) ≤ m U ( x / m ) + x l o g m , ∀ m ∈ N + , U ( 1 ) = 1 U(x)\le mU(x/m)+xlogm,\forall m\in \mathbb N_+,U(1)=1 U(x)mU(x/m)+xlogm,mN+,U(1)=1 ∀ x > 1 , U ( x ) ≤ T ( x ) \forall x>1,U(x)\le T(x) x>1,U(x)T(x).
对数以 e e e为底。
A2:
T ′ ( x ) = T ′ ( x / m ) + l o g m , T ′ ( p x ) = T ′ ( x ) + l o g p , T ′ ( p x ) = T ′ ( p x / q ) + l o g q , T ′ ( p x / q ) = T ′ ( x ) + l o g ( p / q ) T'(x)=T'(x/m)+logm,T'(px)=T'(x)+logp,T'(px)=T'(px/q)+logq,T'(px/q)=T'(x)+log(p/q) T(x)=T(x/m)+logm,T(px)=T(x)+logp,T(px)=T(px/q)+logq,T(px/q)=T(x)+log(p/q)
T ′ ( ( 1 + 1 / n ) x ) = T ′ ( x ) + l o g ( 1 + 1 / n ) T'((1+1/n)x)=T'(x)+log(1+1/n) T((1+1/n)x)=T(x)+log(1+1/n)
T ′ ′ ( x ) = l i m n → ∞ T ′ ( ( 1 + 1 / n ) x ) − T ′ ( x ) ( 1 + 1 / n ) x − x = l i m n → ∞ l o g ( 1 + 1 / n ) x / n = 1 / x T''(x)=lim_{n\to\infty}\frac{T'((1+1/n)x)-T'(x)}{(1+1/n)x-x}=lim_{n\to\infty}\frac{log(1+1/n)}{x/n}=1/x T(x)=limn(1+1/n)xxT((1+1/n)x)T(x)=limnx/nlog(1+1/n)=1/x
T ′ ( x ) = l o g x + C 0 , T ( x ) = x l o g x + D 0 x + D 1 T'(x)=logx+C_0,T(x)=xlogx+D_0x+D_1 T(x)=logx+C0,T(x)=xlogx+D0x+D1
T ( x ) − m T ( x / m ) = x l o g x + D 0 x + D 1 − x l o g ( x / m ) − D 0 x − D 1 m = x l o g m + D 1 − D 1 m = x l o g m , D 1 = 0 T(x)-mT(x/m)=xlogx+D_0x+D_1-xlog(x/m)-D_0x-D_1m=xlogm+D_1-D_1m=xlogm,D_1=0 T(x)mT(x/m)=xlogx+D0x+D1xlog(x/m)D0xD1m=xlogm+D1D1m=xlogm,D1=0
T ( 1 ) = 0 + D 0 = 1 , D 0 = 1 T(1)=0+D_0=1,D_0=1 T(1)=0+D0=1,D0=1
T ( x ) = x l o g x + x T(x)=xlogx+x T(x)=xlogx+x
第二问:不一定。
Δ ( x ) = T ( x ) − U ( x ) \Delta(x)=T(x)-U(x) Δ(x)=T(x)U(x),则 Δ ( x ) ≤ m Δ ( x / m ) , Δ ( 1 ) = 0 \Delta(x)\le m\Delta(x/m),\Delta(1)=0 Δ(x)mΔ(x/m),Δ(1)=0. 这一般来说不能导出 Δ ( x ) ≥ 0 , ∀ x > 1 \Delta(x)\ge 0,\forall x>1 Δ(x)0,x>1. 例如: [ 1 , 2 ] [1,2] [1,2]取平缓的负值,在1左侧和2右侧都快速地单调递减。具体反例的构造是平凡的。
注:渐近分析(特别涉及不等式时)往往比较困难。但在对算法做复杂度分析时,我们只需考虑整数值,故往往可以用数学归纳法等做出简单的证明。

猜你喜欢

转载自blog.csdn.net/tritone/article/details/118531759