输入3个各不相同的整数
1)题目:请设计一个算法将输入的3个整数排序。
Algorithm: BUBBLE(A[1,2,3])
flag := false
for i:= 1 to 2 do
if A[i] > A[i+1] then
SWAP(A[i],A[i+1]);
flag := true;
if flag = true then
if A[1]>A[2] then
SWAP(A[1],A[2]);
2)题目:在最坏情况下、平均情况下你的算法分别需要进行多少次的比较?(假设所有可能的输入等概率出现)
解析:最坏情况即是比较次数最多的全逆序,平均情况可以直接枚举所有情况再求期望(注:不同算法答案可能不同);
解答如下:(以三个整数∈集合{1,2,3}为例)
最坏情况下:A[1,2,3] = {3,2,1}, 需要3次比较;
平均情况下:共6种情况,每种情况等概率1/6,笔者的算法只有{1,2,3}一种情况需要2次比较,其余均需要3次比较,故平均需要: 1 6 ∗ 2 + 5 6 ∗ 3 = 17 6 \frac{1}{6}*2+\frac{5}{6}*3= \frac{17}{6} 61∗2+65∗3=617次比较;
3)题目:在最坏情况下将3个不同整数排序至少需要多少次比较?请证明你的结论。
情况 | 对手 |
---|---|
第1次比较a和b | a< b |
第2次若比较a和c | a < c, 此时无法确定b和c的大小关系 |
第3次若比较b和c | b > c, 此时无法确定a和c的大小关系 |
输入3个各不相同的整数
1)题目:请设计一个寻找3个数的中位数的算法。
Algorithm: MIDDLE(A[1,2,3])
max := MAX(A[1],A[2]); /*需且仅需1次比较*/
min := MIN(A[1],A[2]); /*需且仅需1次比较*/
if A[3] > max then
return max;
else
if A[3] > min then
return A[3];
else
return min;
2)题目:在最坏情况下、平均情况下你的算法分别需要进行多少次的比较?(假设所有可能的输入等概率出现)
解析:最坏情况即是比较次数最多的全逆序,平均情况可以直接枚举所有情况再求期望(注:不同算法答案可能不同);
解答如下:(以三个整数∈集合{1,2,3}为例)
最坏情况下:A[1,2,3] = {1,3,2}或{3,1,2}或{2,3,1}或{3,2,1},需要3次比较;
平均情况下:共6种情况,每种情况等概率1/6,只有{1,2,3},{2,1,3}种情况只需要2次比较,其余均需要3次比较,故平均需要: 2 6 ∗ 2 + 4 6 ∗ 3 = 8 3 \frac{2}{6}*2+\frac{4}{6}*3 = \frac{8}{3} 62∗2+64∗3=38次比较;
3)题目:在最坏情况下找出3个不同整数的中位数至少需要多少次比较?请证明你的结论。
定义集合的最小覆盖如下:已知全集U={1,…,n}。给定U的子集组成的集合族S = {S1,…,Sm},找到S的最小子集T,满足 ⋃ S i ∈ T S i = U \bigcup_{S_i \in T} S_i = U ⋃Si∈TSi=U.
1)题目:找出下面算法失败的例子:首先选择S中最大的集合Si,并从全集中将Si中的所有元素删除;然后从S中剩余的集合中挑选最大的并从全集中删除对应元素;重复上述过程直到全集中的所有元素都被覆盖。
2)题目:请设计一个算法计算输入全集的一个集合覆盖,并证明你所设计算法的正确性。
解析:算法只需要对于每个未覆盖元素xi,去遍历子集族,找到一个子集包含该元素,则将该子集加入覆盖,并将其中包括xi的所有元素标记为已覆盖;重复上述过程,直到所有元素全部覆盖或找不到任何一个子集能覆盖某个元素xj(此时不存在集合覆盖);算法正确性证明只需抓住元素个数有限,而每次只要找到一个包含未覆盖元素xi的子集S即能减少至少1个未覆盖元素即可;
算法伪码如下: 设(全集U={x1,x2,xn}, 子集为S1,S2,.,Sk)
Algorithm: MINCOVER(S1,S2,..,SK)
mincover := {
};
for each xi in U: /*初始化所有元素为未标记*/
xi is unvisited;
for each unvisited xi in U:
if found Sj has xi: /*这里需要在未加入覆盖中的子集中寻找*/
make each xk in Sj visited;
join Sj into mincover;
else:
return NULL; /*此时不存在集合覆盖*/
return mincover;
3)题目:你所设计的算法能否保证总是得出最小覆盖?如果不能,请针对你的算法设计一个反例。
题目:…请将上述3种方案分别写成算法,并通过举反例的方式证明这3个算法的“不正确性”。
题目:HORNER算法是用来计算多项式 P ( x ) = a n x n + a n − 1 x n − 1 + . . + a 1 x + a 0 P(x) = a_nx^n + a_{n-1}x^{n-1}+..+a_1x+a_0 P(x)=anxn+an−1xn−1+..+a1x+a0的,请证明其正确性。
解析:HORNER算法本质即为秦九劭算法, 采用了迭代的思想,故正确性证明可采用同样使用了迭代思想的数学归纳法;
证明:
i) 当n = 1 时,p = a0 = P(x), 易知正确;
ii) 假设当n = k时算法正确,即 p = P ( x ) = ∑ a i x i ( i : 0 → k ) p = P(x) = ∑a_ix^i (i : 0 \rightarrow k) p=P(x)=∑aixi(i:0→k);则当n = k+1时,由假设知,循环的倒数第二次: p = ∑ a i x i − 1 ( i : 1 → k + 1 ) p=∑a_ix^i-1 (i :1 \rightarrow k+1) p=∑aixi−1(i:1→k+1),故最后一遍循环: p = p ∗ x + A [ 0 ] = ∑ a i x i + a 0 ( i : 1 → k + 1 ) = ∑ a i x i ( i : 0 → k + 1 ) p = p*x+A[0] = ∑aix^i+a_0 (i :1 \rightarrow k+1) = ∑a_ix^i (i : 0 \rightarrow k+1) p=p∗x+A[0]=∑aixi+a0(i:1→k+1)=∑aixi(i:0→k+1)
综上:归纳可得算法对一切n成立;
INT-MULT算法用来计算两个非负整数y、z的乘积
1)题目:令c = 2, 请证明算法的正确性。
解析:由算法易得算法的递推公式:
F ( y , z ) = F ( c y , ⌊ z c ⌋ ) + y ∗ ( z m o d c ) F(y,z) = F(cy,\lfloor \frac{z}{c} \rfloor) + y*(z \mod c) F(y,z)=F(cy,⌊cz⌋)+y∗(zmodc)
设 z = z n , z i = c ∗ z i − 1 + r n z = z_n, z_i = c*z_{i-1} + r_n z=zn,zi=c∗zi−1+rn ,即 z i c = z i − 1 , z i m o d c = r i , 特 殊 地 : z 0 = 0 \frac{zi}{c} = z_{i-1}, z_i \mod c = r_i, 特殊地:z_0 = 0 czi=zi−1,zimodc=ri,特殊地:z0=0
故递推公式可变形为: F ( y , z n ) = y ∗ Σ c i ∗ r n − i ( i : 0 → n − 1 ) F(y,z_n) = y*Σc^i*r_{n-i} (i : 0 \rightarrow n-1) F(y,zn)=y∗Σci∗rn−i(i:0→n−1),
通过变形其实可以清楚认识到算法的本质其实就是得到z的c进制形式,然后逐位与y相乘,故算法的进行(递归的层数)与y无关(y仅作为一个系数参数)因此任意y, 当算法对所有的z∈N成立时,即可得算法的正确性;
算法正确性证明如下:(采用数学归纳法)
i) 当 z = 1 z=1 z=1时, F ( y , 1 ) = y ∗ 2 0 = y ∗ 1 F(y,1) = y*2^0 = y*1 F(y,1)=y∗20=y∗1, 易知成立;
ii) 假设当 z ≤ k ( k > 1 ) z\leq k(k>1) z≤k(k>1)时算法成立,即 y ∗ z = F ( y , z ) y*z = F(y,z) y∗z=F(y,z), 则当z = k+1时, F ( y , k + 1 ) = F ( 2 y , ⌊ k + 1 2 ⌋ ) + y ∗ ( ( k + 1 ) m o d 2 ) F(y,k+1) = F(2y,\lfloor \frac{k+1}{2}\rfloor)+y*((k+1) \mod 2) F(y,k+1)=F(2y,⌊2k+1⌋)+y∗((k+1)mod2),对k奇偶分类讨论如下:
① 当 k = 2 m k = 2m k=2m时, F ( y , 2 m + 1 ) = F ( 2 y , ⌊ 2 m + 1 2 ⌋ ) + y = F ( 2 y , m ) + y = 2 y ∗ m + y = y ∗ k + y = y ∗ ( k + 1 ) F(y,2m+1) = F(2y,\lfloor \frac{2m+1}{2}\rfloor) + y = F(2y,m)+y = 2y*m+y = y*k+y = y*(k+1) F(y,2m+1)=F(2y,⌊22m+1⌋)+y=F(2y,m)+y=2y∗m+y=y∗k+y=y∗(k+1), 成立;
② 当 k = 2 m + 1 k = 2m+1 k=2m+1时, F ( y , 2 m + 2 ) = F ( 2 y , m + 1 ) + 0 = 2 y ∗ ( m + 1 ) = y ∗ ( k + 1 ) F(y,2m+2) = F(2y,m+1)+0 = 2y*(m+1) = y*(k+1) F(y,2m+2)=F(2y,m+1)+0=2y∗(m+1)=y∗(k+1), 成立;
综上:归纳可得算法对所有的z∈N成立,故算法正确,得证;
2)题目:令c为任意一个不小于2的常数,请证明算法的正确性。
解析:同 1) 解析;
算法正确性证明如下:(同理与 1)证明)
i) 当 z = 1 z=1 z=1时, F ( y , 1 ) = y ∗ c 0 = y ∗ 1 F(y,1) = y*c^0 = y*1 F(y,1)=y∗c0=y∗1, 易知正确;
ii) 假设当 z ≤ k ( k > 1 ) z\leq k(k>1) z≤k(k>1)时算法成立,即 y ∗ z = F ( y , z ) , ( z ≤ k ) y*z = F(y,z) ,(z\leq k) y∗z=F(y,z),(z≤k), 则当 z = k + 1 z = k+1 z=k+1时, F ( y , k + 1 ) = F ( c y , ⌊ k + 1 c ⌋ ) + y ∗ ( ( k + 1 ) m o d c ) F(y,k+1) = F(cy,\lfloor \frac{k+1}{c}\rfloor)+y*((k+1) \mod c) F(y,k+1)=F(cy,⌊ck+1⌋)+y∗((k+1)modc),
令 ⌊ k + 1 c ⌋ = q , ( k + 1 ) m o d c = r \lfloor\frac{k+1}{c}\rfloor = q,(k+1) \mod c = r ⌊ck+1⌋=q,(k+1)modc=r, 由带余除法知:
k + 1 = c q + r k+1=cq+r k+1=cq+r, 则 F ( y , k + 1 ) = F ( c y , q ) + y ∗ r = y ∗ c q + y ∗ r = y ∗ ( c q + r ) = y ∗ ( k + 1 ) F(y,k+1) = F(cy,q)+y*r = y*cq+y*r = y*(cq+r) = y*(k+1) F(y,k+1)=F(cy,q)+y∗r=y∗cq+y∗r=y∗(cq+r)=y∗(k+1), 成立;
综上:归纳可得算法对所有的z∈N成立,故算法正确,得证;
题目:···请针对输入的取值情况,分析下面算法的平均复情况时间复杂度(一个operation的代价记为1)