算法导论第二章笔记

第二章内容:
1.一个重要概念: loop invariant.
2.规范化伪代码.
3.复合数据一般组合成对象,由attribute或field组成.
4.数组的属性:

一般取名:A或大写字母
length[A]:A的长度

5.空指针用符号 N I L NIL NIL表示v.
6. a n d / o r and/or and/or短路.
7.基于RAM和种种假设的算法分析.
8.常用设计策略:incremental和divide-and-conquer.
练习:
2.1.1:

begin-->
key:31
A:<31,41,59,26,41,58>
-->
key:41
A:<31,41,59,26,41,58>
-->
key:59
A:<31,41,59,26,41,58>
-->
key:26
A:<31,31,41,59,41,58>
->
key:26
A:<26,31,41,59,41,58>
-->
key:41
A:<26,31,41,59,59,58>
->
key:41
A:<26,31,41(1),41(2),59,58>
-->
key:59
A:<26,31,41(1),41(2),59,58>
-->
key:58
A:<26,31,41(1),41(2),59,59>
->
key:58
A:<26,31,41(1),41(2),58,59>
-->end

2.1.2.

INSERTION-SORT(A)
for j ← 2 to length[A]
	do key ← A[j]
	i ← j-1
	while i > 0 and A[i] < key
		do A[i+1] ← A[i]
			i ← i-1
	A[i+1] ←key
//事实上传入比较函数后:
INSERTION-SORT(A,compare())
for j ← 2 to length[A]
	do key ← A[j]
	i ← j-1
	while i > 0 and compare(A[i],key) > 0
		do A[i+1] ← A[i]
			i ← i-1
	A[i+1] ← key

2.1.3.

LINEAR-SEARCH(A,key)
	for j ← 1 to length[A]
		if key = A[j]
			then return j
	return NIL

初始化.很明显 A [ 0 ] A[0] A[0]不可能为所求下标.
保持.每轮循环结束保持 k e y ≠ A [ j ] key \neq A[j] key̸=A[j].
终止. j &gt; l e n g t h [ A ] j&gt;length[A] j>length[A]时循环结束,但这证明A中不包括key,应该返回NIL.
2.1.4:
形式化描述: C [ i ] = A [ i ] + B [ i ] + f C[i]=A[i]+B[i]+f C[i]=A[i]+B[i]+f,其中f为进位

ADD(A,B)
	f ← 0
	for j ← 1 to length[A]
		C[j] ← A[j] + B[j] + f
		f ← C[j] ÷ 10
		C[j] ← C[j] % 10
	C[length[A]+1] ← f

2.2.1:
f ( n ) = Θ ( n 3 ) f(n)=\Theta(n^3) f(n)=Θ(n3)
2.2.2:
循环不变式是:
A [ 0... j − 1 ] A[0...j-1] A[0...j1]是已排数组 A [ j . . . n ] A[j...n] A[j...n]是待排数组
开始: A [ 0 ] A[0] A[0]显然是正确的排序
保持: A [ 0... j − 1 ] A[0...j-1] A[0...j1]是已排数组,而 A [ j ] A[j] A[j]被第j小数交换,这就使得 A [ j ] A[j] A[j]大于等于 A [ 0... j − 1 ] A[0...j-1] A[0...j1]的所有数,小于等于 A [ j + 1... n ] A[j+1...n] A[j+1...n]的所有数
终止:j=n-1时循环结束,事实上A[n]是第n小数,A[1…n-1]和A[n]组成给定A的所求排列。
2.2.3:
对于长度为n的数组设置第n+1的虚拟键(not found),待求key落入每个节点的可能性为 1 n + 1 \frac{1}{n+1} n+11,所以单论循环体的运行 f 1 ( n ) = 1 n + 1 + 2 n + 1 + . . . + n n + 1 = n 2 f_1(n)=\frac{1}{n+1}+\frac{2}{n+1}+...+\frac{n}{n+1}=\frac{n}{2} f1(n)=n+11+n+12+...+n+1n=2n,最坏情况是查找n次, f 2 ( n ) = n n + 1 f_2(n)=\frac{n}{n+1} f2(n)=n+1n,两种 Θ \Theta Θ表示均为 Θ ( n ) \Theta(n) Θ(n)
2.2.4:
使之变为碰运气的算法(有可能一发即中),而不是谨慎的算法。
2.3.1:

begin-->
A:<3,41,52,26,38,57,9,49>
-->
A:<<3,41,52,26>,<38,57,9,49>>
-->
A:<<<3,41>,<52,26>>,<<38,57>,<9,49>>>
-->
A:<<<<3>,<41>>,<<52>,<26>>>,<<<38>,<57>>,<<9>,<49>>>>
-->
A:<<<3,41>,<26,52>>,<<38,57>,<9,49>>>
-->
A:<<3,26,41,52>,<9,38,49,57>>
-->
A:<3,9,26,38,41,49,52,57>
-->end

2.3.2:

MERGE(A,p,q,r)
	n1 ← q-p+1
	n2 ← r-q
	create arrays L[1...n1] and R[1...n2]
	for i ← to n1
		do L[i] ← A[p+i-1]
	for i ← to n2
		do R[i] ← A[q+i]
	cur1 ← p
	cur2 ← q+1
	cur ← 1
	while cur1 <= n1 and cur2 <= n2
		do if L[cur1]<=R[cur2]
			then A[cur] ← L[cur1]
				cur1 ← cur1 + 1
			else A[cur] ← R[cur2]
				cur2 ← cur2 + 1
		cur ← cur + 1
	while cur1 <= n1
		do A[cur] ← L[cur1]
		cur1 ← cur1 + 1
		cur ← cur + 1
	while cur2 <= n2
		do A[cur] ← L[cur2]
		cur2 ← cur2 + 1
		cur ← cur + 1

2.3.3:
n = 1 n=1 n=1 T ( 2 1 ) = 2 ∗ l g 2 = 2 T(2^1)=2*lg2=2 T(21)=2lg2=2成立
②设 n = k n=k n=k时有 T ( 2 k ) = 2 k l g 2 k = k 2 k T(2^k)=2^klg2^k=k2^k T(2k)=2klg2k=k2k,则 n = k + 1 n=k+1 n=k+1 T ( 2 k + 1 ) = 2 T ( 2 k + 1 / 2 ) + 2 k + 1 = k 2 k + 1 + 2 k + 1 = ( k + 1 ) 2 k + 1 T(2^{k+1})=2T(2^{k+1}/2)+2^{k+1}=k2^{k+1}+2^{k+1}=(k+1)2^{k+1} T(2k+1)=2T(2k+1/2)+2k+1=k2k+1+2k+1=(k+1)2k+1也成立
③由①和②及第一数学归纳法得 T ( n ) = n l g n T(n)=nlgn T(n)=nlgn,n为2的整数次幂
2.3.4
T ( n ) = { 1 , n = 1 T ( n − 1 ) + 1 , n &gt; 1 T(n)=\left\{ \begin{aligned} &amp;1 &amp;&amp; ,n=1 \\ &amp;T(n-1)+1 &amp;&amp; ,n&gt;1\\ \end{aligned} \right. T(n)={1T(n1)+1,n=1,n>1
2.3.5

BIN_SEARCH(A,v)
	l ← 1
	r ← length[A]
	while r >= l
		m ← (l+r)/2
		do  if A[m] = v
			then return m
			else if A[m] < v
			then r = m-1
			else l = m+1
	return NIL

复杂度分析用搜索树说明即可
2.3.6
可以,因为A[1…j-1]是有序的。
2.3.7
先排序集合复杂度为 Θ ( n l g n ) \Theta(nlgn) Θ(nlgn),对于 S S S中的每一个 S [ j ] &lt; = x / 2 S[j]&lt;=x/2 S[j]<=x/2在S[j+1…n]中寻找S[i]=x-S[j],复杂度为 Θ ( n l g n ) \Theta(nlgn) Θ(nlgn)所以总复杂度为 Θ ( n l g n ) \Theta(nlgn) Θ(nlgn)
2-1:
a.证明:
T 1 ( n , k ) = n k O ( k 2 ) = O ( n k ) . T_1(n,k)=\frac{n}{k}O(k^2)=O(nk). T1(n,k)=knO(k2)=O(nk).
b.证明:
T 2 ( n , k ) = O ( n ) ⋅ lg ⁡ ( n k ) = O ( n ⋅ lg ⁡ ( n k ) ) T_2(n,k)=O(n)\cdot \lg (\frac{n}{k})=O(n\cdot \lg (\frac{n}{k})) T2(n,k)=O(n)lg(kn)=O(nlg(kn))
c.证明:
首先 k = lg ⁡ n k=\lg n k=lgn即可.
其次我们希望其拥有最好的时间复杂度,那么有:
T 1 = O ( T 2 ) ⇔ c 1 n k = c 2 n lg ⁡ n k ⇔ k + lg ⁡ k = c lg ⁡ n T_1=O(T_2)\Leftrightarrow c_1nk=c_2n\lg \frac{n}{k}\Leftrightarrow k+\lg k =c\lg n T1=O(T2)c1nk=c2nlgknk+lgk=clgn
所以实践中近似选择 k = c lg ⁡ n k=c\lg n k=clgn,会比较好.
2-2,2-3,2-4暂略。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值