算法设计与分析常见习题及详解

无论在以后找工作还是面试中,都离不开算法设计与分析。本博文总结了相关算法设计的题目,旨在帮助加深对贪心算法、动态规划、回溯等算法的理解。

1、计算下述算法执行的加法次数:

输入:n=2^t   //t为整数
输出:加法次数 k
K=0
while n>=1 do
    for j=1 to n do
         k:= k+1
    n= n/2
return k

解析:第一次循环执行n次加法,第二次循环执行1/2次加法,第三次循环执行1/ 2 2 = 1 / 4 2^2=1/4 22=1/4次加法…因此,上述算法执行加法的次数为 n + 1 2 n + 1 4 n + . . . + 1 n+\frac{1}{2}n+\frac{1}{4}n+...+1 n+21n+41n+...+1= n + n − 1 2 n + 1 2 n − 1 4 n + . . . . − 1 n+n-\frac{1}{2}n+\frac{1}{2}n-\frac{1}{4}n+....-1 n+n21n+21n41n+....1=2n-1


2、考虑下面每对函数 f(n) 和 g(n) ,如果它们的阶相等则使用Θ记号,否则使用 O 记号表示它们的关系
f ( n ) = ( n 2 − n ) / 2 , g ( n ) = 6 n f(n)=(n^2-n)/2,g(n)=6n f(n)=(n2n)/2g(n)=6n
解析
前导知识:
1 < l o g n < n < n l o g n < n 2 < n 3 < 2 n < n ! < n n 11<logn<n<nlogn<n2<n3<2n<n!<nn
g ( n ) = O ( f ( n ) ) g(n)=O(f(n)) g(n)=O(f(n)),因为 f ( n ) = Θ ( n 2 ) , g ( n ) = Θ ( n ) f(n)=\Theta(n^2),g(n)=\Theta(n) f(n)=Θ(n2),g(n)=Θ(n)
f ( n ) = n + 2 n , g ( n ) = n 2 f(n)=n+2\sqrt{n},g(n)=n^2 f(n)=n+2n ,g(n)=n2
解析 f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n)),因为 f ( n ) = Θ ( n ) , g ( n ) = Θ ( n 2 ) f(n)=\Theta(n),g(n)=\Theta(n^2) f(n)=Θ(n),g(n)=Θ(n2)
f ( n ) = n + n l o g n , g ( n ) = n n f(n)=n+nlogn,g(n)=n\sqrt{n} f(n)=n+nlogn,g(n)=nn
解析: f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n)),因为 f ( n ) = Θ ( n l o g n ) , g ( n ) = Θ ( n 3 2 ) f(n)=\Theta(nlogn),g(n)=\Theta(n^\frac{3}{2}) f(n)=Θ(nlogn),g(n)=Θ(n23)
f ( n ) = 2 ( l o g n ) 2 , g ( n ) = l o g n + 1 f(n)=2(log^n)^2,g(n)=logn+1 f(n)=2(logn)2,g(n)=logn+1
解析 g ( n ) = O ( f ( n ) ) g(n)=O(f(n)) g(n)=O(f(n))
f ( n ) = l o g ( n ! ) , g ( n ) = n 1.05 f(n)=log(n!),g(n)=n^{1.05} f(n)=log(n!),g(n)=n1.05
解析: f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n))


3、在表1.1中填入 true 或 false
算法设计与分析常见习题及详解_第1张图片
解析:利用上题的前导知识就可以得出。


4、对于下面每个函数 f(n),用f(n) =Θ(g(n))的形式,其中g(n)要尽可能简洁,然后按阶递增序排列它们(最后一列)
( n − 2 ) ! = Θ ( ( n − 2 ) ! ) (n-2)!=\Theta((n-2)!) (n2)!=Θ((n2)!)
5 l o g ( n + 100 ) 10 = Θ ( l o g n ) 5log(n+100)^{10}=\Theta(logn) 5log(n+100)10=Θ(logn)
2 2 n = Θ ( 4 n ) 2^{2n}=\Theta(4^n) 22n=Θ(4n)
0.001 n 4 + 3 n 3 + 1 = Θ ( n 4 ) 0.001n^4+3n^3+1=\Theta(n^4) 0.001n4+3n3+1=Θ(n4)
( l n n ) 2 = Θ ( l n 2 n ) (ln n)^2=\Theta(ln^2n) (lnn)2=Θ(ln2n)
n 3 + l o g n = Θ ( n 3 ) \sqrt[3]n+logn=\Theta(\sqrt[3]n) 3n +logn=Θ(3n )
3 n = Θ ( 3 n ) 3^n=\Theta(3^n) 3n=Θ(3n)
l o g ( n ! ) = Θ ( n l o g n ) log(n!)=\Theta(nlogn) log(n!)=Θ(nlogn)
l o g ( n n + 1 ) = Θ ( n l o g n ) log(n^{n+1})=\Theta(nlogn) log(nn+1)=Θ(nlogn)
1 + 1 2 + . . . . + 1 n = Θ ( l o g n ) 1+\frac{1}{2}+....+\frac{1}{n}=\Theta(logn) 1+21+....+n1=Θ(logn)
解析:最后一个用到了调和公式: ∑ k = 1 n 1 k = l o g n + O ( 1 ) \sum_{k=1}^{n}\frac{1}{k}=logn+O(1) k=1nk1=logn+O(1)
按阶递增的顺序排列:
1 + 1 2 + . . . . + 1 n 1+\frac{1}{2}+....+\frac{1}{n} 1+21+....+n1 5 l o g ( n + 100 ) 10 5log(n+100)^{10} 5log(n+100)10 ( l n n ) 2 (ln n)^2 (lnn)2 n 3 + l o g n \sqrt[3]n+logn 3n +logn l o g ( n ! ) log(n!) log(n!) l o g ( n n + 1 ) log(n^{n+1}) log(nn+1) 0.001 n 4 + 3 n 3 + 1 0.001n^4+3n^3+1 0.001n4+3n3+1 3 n 3^n 3n 2 2 n 2^{2n} 22n ( n − 2 ) ! (n-2)! (n2)!


5、求解递推方程
前导知识:主定理
算法设计与分析常见习题及详解_第2张图片
前导知识:递归树:
例子:递归树是一棵节点带权的二叉树,初始递归树只有一个结点,标记为权重W(n),然后不断进行迭代,最后直到树种不再含有权为函数的结点为止,然后将树根结点到树叶节点的全部权值加起来,即为算法的复杂度。以二路归并排序算法的递推方程为例子进行递归树讲解。
已知 W ( n ) = 2 W ( n / 2 ) + n − 1 W(n)=2W(n/2)+n−1 W(n)=2W(n/2)+n1,并且W(1)=0,递归树求解过程如下图:
算法设计与分析常见习题及详解_第3张图片
(1) T ( n ) = T ( n − 1 ) + n 2 , T ( 1 ) = 1 T(n)=T(n-1)+n^2,T(1)=1 T(n)=T(n1)+n2,T(1)=1
解析
T ( n − 1 ) = T ( n − 2 ) + ( n − 1 ) 2 T(n-1)=T(n-2)+(n-1)^2 T(n1)=T(n2)+(n1)2
T ( n − 2 ) = T ( n − 3 ) + ( n − 2 ) 2 T(n-2)=T(n-3)+(n-2)^2 T(n2)=T(n3)+(n2)2
T ( n − 3 ) = T ( n − 4 ) + ( n − 3 ) 2 T(n-3)=T(n-4)+(n-3)^2 T(n3)=T(n4)+(n3)2

因此,将上述各式相加,得到 T ( n ) = 1 + 2 2 + 3 3 + . . . + n 2 = n ( n + 1 ) ( 2 n + 1 ) 6 T(n)=1+2^2+3^3+...+n^2=\frac{n(n+1)(2n+1)}{6} T(n)=1+22+33+...+n2=6n(n+1)(2n+1)

(2) T ( n ) = 9 T ( n / 3 ) + n , T ( 1 ) = 1 T(n)=9T(n/3)+n,T(1)= 1 T(n)=9T(n/3)+n,T(1)=1
解析 a = 9 , b = 3 a=9,b=3 a=9,b=3,因此, n l o g b a = n l o g 3 9 = n 2 , f ( n ) = n n^{log_b^a}=n^{log_3^9}=n^2,f(n)=n nlogba=nlog39=n2,f(n)=n
因为, f ( n ) < O ( n 2 ) f(n)f(n)<O(n2),因此, T ( n ) = O ( n 2 ) T(n)=O(n^2) T(n)=O(n2)

(3) T ( n ) = T ( n / 2 ) + T ( n / 4 ) + c n , T ( 1 ) = 1 T(n)=T(n/2) + T(n/4) +cn,T(1)=1 T(n)=T(n/2)+T(n/4)+cnT(1)=1
解析
算法设计与分析常见习题及详解_第4张图片
(3) T ( n ) = 5 T ( n / 2 ) + ( n l o g n ) 2 , T ( 1 ) = 1 T(n)=5T(n/2) + (nlogn)^2,T(1)=1 T(n)=5T(n/2)+(nlogn)2T(1)=1
解析 a = 5 , b = 2 , n l o g b a = n l o g 2 5 , f ( n ) = ( n l o g n ) 2 a=5,b=2,n^{log_b^a}=n^{log_2^5},f(n)=(nlogn)^2 a=5,b=2,nlogba=nlog25,f(n)=(nlogn)2,由于, n l o g 2 5 > O ( f ( n ) ) n^{log_2^5}>O(f(n)) nlog25>O(f(n)),因此,T(n)= O ( n l o g 2 5 ) O(n^{log_2^5}) O(nlog25)


5、设A是 n 个非0实数构成的数组,设计一算法重排数组的数,使得负数都在正数的前面。
要求时间、空间复杂性为 O(n)和O(1)
解析:由于时间复杂度为O(n),空间复杂度为O(1),说明只需要遍历一次数组,不需要额外的存储空间,就能完成该问题的求解。
算法:

  • 从右向左扫描直到找到第一个负数A[p]
  • 从左向右扫描直到找到第一个正数A[q]
  • 若p>q,则交换A[p]、A[q]
  • 若p<=q,则停止,否则重复上述步骤

6、给定含 n 个不同的数的数组 L = < X 1 , … , X n L=L=<X1,,Xn>. 如果 L 中存在 X i X_i Xi 使 x 1 < x 2 < … < X i > X i + 1 > … > x n x_1X_i+1>…>x_n x1<x2<<Xi>Xi+1>>xn 则说 L 是单峰的,并称 x i x_i xi 是 L的峰顶。假设 L 是单峰的,设计算法找到 L 的峰顶。
解析用二分法

  • 若|L|=3,则L[2]即为所求
  • 若|L|>3,则取k=[n/2],检查若L[k-1]L[k+1],则找到
  • 否则,若L[k-1]L[k]>L[k+1],说明单峰在左边,继续进行二分查找

7、设A 是 n 个不同的数排好序的数组,给定数 L 和 U , L 解析:一般对于已经排好序的数组相关的算法,可以想想是否可以用到二分算法。
使用二分查找

  • 用二分查找法找到等于或大于L的最小的位置k,等于的情况k+1(因为题目要求的是大于)
  • 类似的用二分查找找到等于或小于U的最大数的位置j(等于的情况j-1)
  • 输出从k到j的数

8、用动态规划算法求解下面的组合优化问题:
m a x { g 1 ( x 1 ) + g 2 ( x 2 ) + g 3 ( x 3 ) } max\{g_1(x_1)+g_2(x_2)+g_3(x_3)\} max{g1(x1)+g2(x2)+g3(x3)}
x 1 2 + x 2 2 + x 3 2 < = 10 x_1^2+x_2^2+x_3^2 <= 10 x12+x22+x32<=10
x1, x2, x3 为非负整数
其中函数 g1(x), g2(x), g3(x) 的值给在下表中
算法设计与分析常见习题及详解_第5张图片

解析:设 F k ( x ) F_k(x) Fk(x)表示目标函数的最大值
这里设置标志函数 x k ( x ) x_k(x) xk(x),表示当目标函数取到最大时,分配给第k个 g k g_k gk的参数值
因此有:
F k ( x ) = m a x { 0 < = x k < = ⌊ x ⌋ } { F k − 1 ( x − x k ) + g k ( x k ) } F_k(x)=max_{\{0<=x_k<=\left \lfloor x \right \rfloor \}}\{ F_{k-1}(x-x_k)+g_k(x_k) \} Fk(x)=max{0<=xk<=x}{Fk1(xxk)+gk(xk)}
F 1 ( x ) = g 1 ( ⌊ x ⌋ ) F_1(x)=g_1(\left \lfloor \sqrt x \right \rfloor) F1(x)=g1(x )
首先计算 F 1 ( x ) F_1(x) F1(x)
F 1 ( 0 ) = 2 , x 1 ( x ) = 0 F_1(0)=2,x_1(x)=0 F1(0)=2,x1(x)=0,
F 1 ( 1 ) = 4 , F 1 ( 2 ) = 4 , F 1 ( 3 ) = 4 , x 1 ( x ) = 1 F_1(1)=4,F_1(2)=4,F_1(3)=4,x_1(x)=1 F1(1)=4,F1(2)=4,F1(3)=4,x1(x)=1,
F 1 ( 4 ) = 7 , F 1 ( 5 ) = 7 , F 1 ( 6 ) = 7 , F 1 ( 8 ) = 7 , x 1 ( x ) = 2 F_1(4)=7,F_1(5)=7,F_1(6)=7,F_1(8)=7,x_1(x)=2 F1(4)=7,F1(5)=7,F1(6)=7,F1(8)=7,x1(x)=2,
F 1 ( 9 ) = 11 , F 1 ( 10 ) = 11 , x 1 ( x ) = 3 F_1(9)=11,F_1(10)=11,x_1(x)=3 F1(9)=11,F1(10)=11,x1(x)=3
计算 F 2 ( x ) F_2(x) F2(x):
F 2 ( 0 ) = m a x { g 2 ( 0 ) + F 1 ( 0 ) } = 7 , x 2 ( x ) = 0 F_2(0)=max{\{ g_2(0)+F_1(0) \}}=7,x_2(x)=0 F2(0)=max{g2(0)+F1(0)}=7,x2(x)=0
F 2 ( 1 ) = m a x { g 2 ( 0 ) + F 1 ( 1 ) , g 2 ( 1 ) + F 1 ( 0 ) } = 12 , x 2 ( x ) = 1 F_2(1)=max{\{ g_2(0)+F_1(1),g_2(1)+F_1(0) \}}=12,x_2(x)=1 F2(1)=max{g2(0)+F1(1),g2(1)+F1(0)}=12,x2(x)=1
F 2 ( 2 ) = m a x { g 2 ( 0 ) + F 1 ( 2 ) , g 2 ( 1 ) + F 1 ( 1 ) } = 14 , x 2 ( x ) = 1 F_2(2)=max{\{ g_2(0)+F_1(2) ,g_2(1)+F_1(1)\}}=14,x_2(x)=1 F2(2)=max{g2(0)+F1(2),g2(1)+F1(1)}=14,x2(x)=1
F 2 ( 3 ) = m a x { g 2 ( 0 ) + F 1 ( 3 ) , g 2 ( 1 ) + F 1 ( 2 ) } = 14 , x 2 ( x ) = 1 F_2(3)=max{\{ g_2(0)+F_1(3),g_2(1)+F_1(2) \}}=14,x_2(x)=1 F2(3)=max{g2(0)+F1(3),g2(1)+F1(2)}=14,x2(x)=1
F 2 ( 4 ) = m a x { g 2 ( 0 ) + F 1 ( 4 ) , g 2 ( 1 ) + F 1 ( 3 ) , g 2 ( 2 ) + F 1 ( 0 ) } = 18 , x 2 ( x ) = 2 F_2(4)=max{\{ g_2(0)+F_1(4),g_2(1)+F_1(3),g_2(2)+F_1(0) \}}=18,x_2(x)=2 F2(4)=max{g2(0)+F1(4),g2(1)+F1(3),g2(2)+F1(0)}=18,x2(x)=2
F 2 ( 5 ) = m a x { g 2 ( 0 ) + F 1 ( 5 ) , g 2 ( 1 ) + F 1 ( 4 ) , g 2 ( 2 ) + F 1 ( 1 ) } = 20 , x 2 ( x ) = 2 F_2(5)=max{\{ g_2(0)+F_1(5),g_2(1)+F_1(4),g_2(2)+F_1(1) \}}=20,x_2(x)=2 F2(5)=max{g2(0)+F1(5),g2(1)+F1(4),g2(2)+F1(1)}=20,x2(x)=2
F 2 ( 6 ) = m a x { g 2 ( 0 ) + F 1 ( 6 ) , g 2 ( 1 ) + F 1 ( 5 ) , g 2 ( 2 ) + F 1 ( 2 ) } = 20 , x 2 ( x ) = 2 F_2(6)=max{\{ g_2(0)+F_1(6),g_2(1)+F_1(5),g_2(2)+F_1(2) \}}=20,x_2(x)=2 F2(6)=max{g2(0)+F1(6),g2(1)+F1(5),g2(2)+F1(2)}=20,x2(x)=2
F 2 ( 7 ) = m a x { g 2 ( 0 ) + F 1 ( 7 ) , g 2 ( 1 ) + F 1 ( 6 ) , g 2 ( 2 ) + F 1 ( 3 ) } = 20 , x 2 ( x ) = 2 F_2(7)=max{\{ g_2(0)+F_1(7),g_2(1)+F_1(6),g_2(2)+F_1(3) \}}=20,x_2(x)=2 F2(7)=max{g2(0)+F1(7),g2(1)+F1(6),g2(2)+F1(3)}=20,x2(x)=2
F 2 ( 8 ) = m a x { g 2 ( 0 ) + F 1 ( 8 ) , g 2 ( 1 ) + F 1 ( 7 ) , g 2 ( 2 ) + F 1 ( 4 ) } = 23 , x 2 ( x ) = 2 F_2(8)=max{\{ g_2(0)+F_1(8),g_2(1)+F_1(7),g_2(2)+F_1(4) \}}=23,x_2(x)=2 F2(8)=max{g2(0)+F1(8),g2(1)+F1(7),g2(2)+F1(4)}=23,x2(x)=2
F 2 ( 9 ) = m a x { g 2 ( 0 ) + F 1 ( 9 ) , g 2 ( 1 ) + F 1 ( 8 ) , g 2 ( 2 ) + F 1 ( 5 ) , g 2 ( 3 ) + F 1 ( 0 ) } = 23 , x 2 ( x ) = 2 F_2(9)=max{\{ g_2(0)+F_1(9),g_2(1)+F_1(8),g_2(2)+F_1(5),g_2(3)+F_1(0)\}}=23,x_2(x)=2 F2(9)=max{g2(0)+F1(9),g2(1)+F1(8),g2(2)+F1(5),g2(3)+F1(0)}=23,x2(x)=2
F 2 ( 10 ) = m a x { g 2 ( 0 ) + F 1 ( 10 ) , g 2 ( 1 ) + F 1 ( 9 ) , g 2 ( 2 ) + F 1 ( 6 ) , g 2 ( 3 ) + F 1 ( 1 ) } = 24 , x 2 ( x ) = 3 F_2(10)=max{\{ g_2(0)+F_1(10),g_2(1)+F_1(9),g_2(2)+F_1(6),g_2(3)+F_1(1)\}}=24,x_2(x)=3 F2(10)=max{g2(0)+F1(10),g2(1)+F1(9),g2(2)+F1(6),g2(3)+F1(1)}=24,x2(x)=3
计算 F 3 ( x ) F_3(x) F3(x):
F 3 ( 0 ) = m a x { g 3 ( 0 ) + F 2 ( 0 ) } = 15 , x 2 ( x ) = 0 F_3(0)=max{\{ g_3(0)+F_2(0)\}}=15,x_2(x)=0 F3(0)=max{g3(0)+F2(0)}=15,x2(x)=0
F 3 ( 1 ) = m a x { g 3 ( 0 ) + F 2 ( 1 ) , g 3 ( 1 ) + F 2 ( 0 ) } = 20 , x 2 ( x ) = 0 F_3(1)=max{\{ g_3(0)+F_2(1),g_3(1)+F_2(0)\}}=20,x_2(x)=0 F3(1)=max{g3(0)+F2(1),g3(1)+F2(0)}=20,x2(x)=0
F 3 ( 2 ) = m a x { g 3 ( 0 ) + F 2 ( 2 ) , g 3 ( 1 ) + F 2 ( 1 ) } = 24 , x 2 ( x ) = 1 F_3(2)=max{\{ g_3(0)+F_2(2),g_3(1)+F_2(1)\}}=24,x_2(x)=1 F3(2)=max{g3(0)+F2(2),g3(1)+F2(1)}=24,x2(x)=1
F 3 ( 3 ) = m a x { g 3 ( 0 ) + F 2 ( 3 ) , g 3 ( 1 ) + F 2 ( 2 ) } = 26 , x 2 ( x ) = 1 F_3(3)=max{\{ g_3(0)+F_2(3),g_3(1)+F_2(2)\}}=26,x_2(x)=1 F3(3)=max{g3(0)+F2(3),g3(1)+F2(2)}=26,x2(x)=1
F 3 ( 4 ) = m a x { g 3 ( 0 ) + F 2 ( 4 ) , g 3 ( 1 ) + F 2 ( 3 ) , g 3 ( 2 ) + F 2 ( 0 ) } = 26 , x 2 ( x ) = 1 F_3(4)=max{\{ g_3(0)+F_2(4),g_3(1)+F_2(3),g_3(2)+F_2(0)\}}=26,x_2(x)=1 F3(4)=max{g3(0)+F2(4),g3(1)+F2(3),g3(2)+F2(0)}=26,x2(x)=1
F 3 ( 5 ) = m a x { g 3 ( 0 ) + F 2 ( 5 ) , g 3 ( 1 ) + F 2 ( 4 ) , g 3 ( 2 ) + F 2 ( 1 ) } = 30 , x 2 ( x ) = 1 F_3(5)=max{\{ g_3(0)+F_2(5),g_3(1)+F_2(4),g_3(2)+F_2(1)\}}=30,x_2(x)=1 F3(5)=max{g3(0)+F2(5),g3(1)+F2(4),g3(2)+F2(1)}=30,x2(x)=1
F 3 ( 6 ) = m a x { g 3 ( 0 ) + F 2 ( 6 ) , g 3 ( 1 ) + F 2 ( 5 ) , g 3 ( 2 ) + F 2 ( 2 ) } = 32 , x 2 ( x ) = 1 F_3(6)=max{\{ g_3(0)+F_2(6),g_3(1)+F_2(5),g_3(2)+F_2(2)\}}=32,x_2(x)=1 F3(6)=max{g3(0)+F2(6),g3(1)+F2(5),g3(2)+F2(2)}=32,x2(x)=1
F 3 ( 7 ) = m a x { g 3 ( 0 ) + F 2 ( 7 ) , g 3 ( 1 ) + F 2 ( 6 ) , g 3 ( 2 ) + F 2 ( 3 ) } = 32 , x 2 ( x ) = 1 F_3(7)=max{\{ g_3(0)+F_2(7),g_3(1)+F_2(6),g_3(2)+F_2(3)\}}=32,x_2(x)=1 F3(7)=max{g3(0)+F2(7),g3(1)+F2(6),g3(2)+F2(3)}=32,x2(x)=1
F 3 ( 8 ) = m a x { g 3 ( 0 ) + F 2 ( 8 ) , g 3 ( 1 ) + F 2 ( 7 ) , g 3 ( 2 ) + F 2 ( 4 ) } = 35 , x 2 ( x ) = 2 F_3(8)=max{\{ g_3(0)+F_2(8),g_3(1)+F_2(7),g_3(2)+F_2(4)\}}=35,x_2(x)=2 F3(8)=max{g3(0)+F2(8),g3(1)+F2(7),g3(2)+F2(4)}=35,x2(x)=2
F 3 ( 9 ) = m a x { g 3 ( 0 ) + F 2 ( 9 ) , g 3 ( 1 ) + F 2 ( 8 ) , g 3 ( 2 ) + F 2 ( 5 ) , g 3 ( 3 ) + F 2 ( 0 ) } = 37 , x 2 ( x ) = 2 F_3(9)=max{\{ g_3(0)+F_2(9),g_3(1)+F_2(8),g_3(2)+F_2(5),g_3(3)+F_2(0)\}}=37,x_2(x)=2 F3(9)=max{g3(0)+F2(9),g3(1)+F2(8),g3(2)+F2(5),g3(3)+F2(0)}=37,x2(x)=2
F 3 ( 10 ) = m a x { g 3 ( 0 ) + F 2 ( 10 ) , g 3 ( 1 ) + F 2 ( 9 ) , g 3 ( 2 ) + F 2 ( 6 ) , g 3 ( 3 ) + F 2 ( 1 ) } = 37 , x 2 ( x ) = 2 F_3(10)=max{\{ g_3(0)+F_2(10),g_3(1)+F_2(9),g_3(2)+F_2(6),g_3(3)+F_2(1)\}}=37,x_2(x)=2 F3(10)=max{g3(0)+F2(10),g3(1)+F2(9),g3(2)+F2(6),g3(3)+F2(1)}=37,x2(x)=2

备忘录:
算法设计与分析常见习题及详解_第6张图片
因此,问题的解是:在 x 1 = 1 , x 2 = 2 , x 3 = 2 x_1=1,x_2=2,x_3=2 x1=1,x2=2,x3=2时,得到 g 1 ( x 1 ) + g 2 ( x 2 ) + g 3 ( x 3 ) g_1(x_1)+g_2(x_2)+g_3(x_3) g1(x1)+g2(x2)+g3(x3)得到最大值37


7、设A=< X 1 , X 2 , … , X n X_1, X_2, …, X_n X1,X2,,Xn> 是n个不等的整数的序列,A的一个单调递增子序列是序列< X i 1 , X i 2 , … , X i k X_{i1}, X_{i2}, …, X_{ik} Xi1,Xi2,,Xik > 使得 i 1 < i 2 < … < i k i1i1<i2<<ik,且 X i 1 < X i 2 < … < X i k X_{i1}< X_{i2} < … < X_{ik} Xi1<Xi2<<Xik. 子序列的长度是指序列中整数的个数。设计算法求最长的单调递增子序列,分析算法复杂度。设输入实例是 A= <2, 8, 4, -4, 5, 9, 11>. 给出算法的计算过程和最后解。
解析:因为需要求最长,并且有条件限制,因此可以用动态规划试试。
使用动态规划技术,对 i = 1 , 2 , 3... n i=1,2,3...n i=1,2,3...n(其中i表示元素的序号),考虑以 x i x_i xi作为最长单调子序列的最后项(结尾),使用 C [ i ] C[i] C[i]表示以 x i x_i xi为最长子序列的最后项的长度。
则:
C [ i ] = m a x { 1 + C [ j ] } C[i]=max\{1+C[j]\} C[i]=max{1+C[j]},其中i>j>=1
否则(如果不存在i>i>=1,使得 ( x i > x j ) (x_i>x_j) (xi>xj)或i=1时), C [ i ] = 1 C[i]=1 C[i]=1
使用 k [ i ] = j k[i]=j k[i]=j表示当 C [ i ] C[i] C[i]取得最大值的时候,j的取值
对于给定实例:A= <2, 8, 4, -4, 5, 9, 11>
C[1]=1,k[1]=0
C [ 2 ] = m a x { 1 + C [ 1 ] } = 2 , k [ 2 ] = 1 C[2]=max\{ 1+C[1]\}=2,k[2]=1 C[2]=max{1+C[1]}=2,k[2]=1
C [ 3 ] = m a x { 1 + C [ 1 ] } = 2 , k [ 3 ] = 1 C[3]=max\{ 1+C[1]\}=2,k[3]=1 C[3]=max{1+C[1]}=2,k[3]=1
C [ 4 ] = 1 , k [ 4 ] = 0 C[4]=1,k[4]=0 C[4]=1,k[4]=0
C [ 5 ] = m a x { 1 + C [ 1 ] , C [ 3 ] + 1 , C [ 4 ] + 1 } = 3 , k [ 5 ] = 3 C[5]=max\{ 1+C[1],C[3]+1,C[4]+1\}=3,k[5]=3 C[5]=max{1+C[1],C[3]+1,C[4]+1}=3,k[5]=3
C [ 6 ] = m a x { 1 + C [ 1 ] , 1 + C [ 2 ] , 1 + C [ 3 ] , 1 + C [ 4 ] , 1 + C [ 5 ] } = 4 , k [ 6 ] = 5 C[6]=max\{ 1+C[1],1+C[2],1+C[3],1+C[4],1+C[5]\}=4,k[6]=5 C[6]=max{1+C[1],1+C[2],1+C[3],1+C[4],1+C[5]}=4,k[6]=5
C [ 7 ] = m a x { 1 + C [ 1 ] , 1 + C [ 2 ] , 1 + C [ 3 ] , 1 + C [ 4 ] , 1 + C [ 5 ] , 1 + C [ 6 ] } = 5 , k [ 7 ] = 6 C[7]=max\{ 1+C[1],1+C[2],1+C[3],1+C[4],1+C[5],1+C[6]\}=5,k[7]=6 C[7]=max{1+C[1],1+C[2],1+C[3],1+C[4],1+C[5],1+C[6]}=5,k[7]=6
因此,最长子序列长度为5,最长递增子序列为<2,4,5,9,11>
因为,对于每个i,要检索比i小的所有j,需要O(n)的时间,i的取值有n种,因此,时间复杂度为O( n 2 n^2 n2)

i 1 2 3 4 5 6 7
A[i] 2 8 4 -4 5 9 11
C[i] 1 1 1 1 3 4 5
K[i] 0 1 1 0 3 5 6

8、有n个底面为长方形(各长方形长度表示为 li)的货柜需租用库房存放。如果货柜都需放在地面,且所有货柜的底面宽度等于库房的宽度,库房总长度 D满足:li<=D, ∑ \sum li>D。 再设第i号货柜的仓储效益是 vi, 请问如何放入库房可以获得最大收益?设计求解算法及伪码。(0-1背包问题)
解析:类似于0-1背包问题,库房的长度相当于背包的容量,每个货柜的效益相当于每个背包的价值:
m a x ∑ i = 1 n v i ∗ x i max \sum_{i=1}^nv_i*x_i maxi=1nvixi
∑ l i ∗ x i < = D \sum l_i*x_i<=D lixi<=D
F k ( y ) F_k(y) Fk(y)表示只允许装前k个货柜,库房长度为y时 的效益最大值:
F k ( y ) = m a x { F k − 1 ( y − l k ) + v k , F k − 1 ( y ) } , l k < = y < = D F_k(y)=max\{ F_{k-1}(y-l_k)+v_k,F_{k-1}(y)\},l_k<=y<=D Fk(y)=max{Fk1(ylk)+vk,Fk1(y)},lk<=y<=D
F k ( y ) = F k − 1 ( y ) , l k > y F_k(y)=F_{k-1}(y),l_k>y Fk(y)=Fk1(y),lk>y
F 1 ( y ) = v i , 当 l 1 < = y 时 , 0 , 当 l i > y 时 F_1(y)=v_i,当l_1<=y时,0,当l_i>y时 F1(y)=vi,l1<=y0,li>y


9、Dijkstra算法要求有向图的边的权是非负实数,请举出反例说明,对于某些含有负数边权的有向 图,Dijkstra不能得到正确的解
解析:Dijkstra最短路径算法对负权图失效,不存在最短路径。
算法设计与分析常见习题及详解_第7张图片
算法设计与分析常见习题及详解_第8张图片


10、给定n个集合 A 1 , . . . A n A_1,...A_n A1,...An,每个集合都由连续的正整数构成,即:
A i = { x ∣ a i < = x < = b i } , a i , x , b i ∈ Z + i = 1 , 2 , . . . . n A_i=\{ x|a_i<=x<=b_i\},a_i,x,b_i∈Z^+ i=1,2,....n Ai={xai<=x<=bi},ai,x,biZ+i=1,2,....n
设计一个算法求最小的集合S,使得对于每个i=1,2…n,| S ∩ A i ≠ ∅ S∩A_i\not =∅ SAi=|,即每个 A i A_i Ai至少包含有S中的一个数
解析:这道题目类似于活动问题,都是要找出相容的活动,并把相容的 活动放入结果集中。在本题中,需要找出相容(一个集合的结束值元素大于另一个集合的开始值元素,则称这两个集合相容)的集合,将这些集合的结束值放到结果集中。
使用贪心算法,对 b i b_i bi从小到大进行排序(正如活动问题中按照结束时间由早到晚进行排序),将 b i b_i bi放入S。将 b i b_i bi记作当前的测试点x,按照顺序依次检查 A 2 , . . . A n A_2,...A_n A2,...An a 1 a_1 a1,若 a 1 < = x a_1<=x a1<=x,说明S已包含该集合 A i A_i Ai中的某个元素(不相容),否则,说明这两个集合不相容,则把 b i b_i bi加入到S中,并将测试点x赋值新的 b i b_i bi,直到测试完所有集合为止,得到的S即为所求解。


11、最小重量机器设计问题: 某设备需4种配件,每种一件,且有三个供应商提供这些配件。下表给出相关的价格和每种配件的重量;从中选择4种配件(的供应商),使得总价值不超过120,且总重量最轻
产品和供应商信息表:
算法设计与分析常见习题及详解_第9张图片

解析:最后问题的解是一个向量(每一种零件选择的对应厂商),设解向量为< x 1 , x 2 . . . . x k x_1,x_2....x_k x1,x2....xk>, x i = j x_i=j xi=j表示第i号零件由j号供应商供货,并且是组合优化问题,也满足多米诺性质,因此可以使用回溯算法。
目标函数:
m i n ∑ w ( x i ) min \sum w(x_i) minw(xi)
∑ v ( x i ) < = 120 , 1 < = i < = 4 \sum v(x_i)<=120, 1<=i<=4 v(xi)<=120,1<=i<=4
搜索树:4层,每层边代表一种零件,权值代表供应商编号。
算法设计与分析常见习题及详解_第10张图片
界函数:目前得到的最优解的重量
代价函数:节点< x 1 , x 2 , . . . . x k x_1,x_2,....x_k x1,x2,....xk>表示已经选择了前k号零件的供应商,正在处理k+1号零件
∑ i = 1 k w ( x i ) + ∑ j = k + 1 n w ( x j ) \sum_{i=1}^kw(x_i)+\sum_{j=k+1}^nw(x_j) i=1kw(xi)+j=k+1nw(xj)


12、子集和问题. 设n个不同的正数构成集合S,求出使得和为某数M的S的所有子集
解析:类似于0-1背包问题。设S={ a 1 , a 2 , . . . . a n a_1,a_2,....a_n a1,a2,....an},求S满足条件 ∑ a i ∈ A a i = M \sum_{a_i∈A}a_i=M aiAai=M的所有子集A。用回溯法。
解向量 < x 1 , x 2 . . . . . x n > , x i = 0 , 1 ,x_i=0,1 <x1,x2.....xn>,xi=0,1,其中 x i x_i xi=1,当且仅当 a i a_i ai∈A,搜索空间为子集树,部分向量 < x 1 , x 2 . . . x k > <x1,x2...xk>表示已经考虑了对 a 1 , a 2 , . . . . a k a_1,a_2,....a_k a1,a2,....ak的选择,结点分支的约束条件为 B ( i ) = ∑ i = 1 k a i x i < M B(i)=\sum_{i=1}^ka_ix_iB(i)=i=1kaixi<M,且, a k + 1 < S − a 1 , a 2 , . . . . a k a_{k+1}ak+1<Sa1,a2,....ak
(分支的条件是前面选择进入结果集的元素和小于M,并且后面要加入的元素值要小于能加入的值)


13、在这里插入图片描述
解析
对于递推方程 T ( n ) = 7 T ( n / 2 ) + n 2 , a = 7 , b = 2 , f ( n ) = n 2 , n l o g b a = n l o g 2 7 T(n)=7T(n/2)+n^2,a=7,b=2,f(n)=n^2,n^{log_b^a}=n^{log_2^7} T(n)=7T(n/2)+n2,a=7,b=2,f(n)=n2,nlogba=nlog27,因此, T ( n ) = Θ ( n l o g 2 7 ) T(n)=\Theta(n^{log_2^7}) T(n)=Θ(nlog27)
对于递推方程 W ( n ) W(n) W(n)也使用主定理, W ( n ) = Θ ( n l o g 4 a ) W(n)=\Theta(n^{log_4^a}) W(n)=Θ(nlog4a)
若使 l o g 4 a < l o g 2 7 log_4^alog4a<log27,有:
l o g 4 a = l o g 2 a l o g 2 4 = l o g 2 a 2 < l o g 2 7 log_4^a=\frac{log_2^a}{log_24}=\frac{log_2^a}{2}log4a=log24log2a=2log2a<log27,因此,a最大为48


14、算法设计与分析常见习题及详解_第11张图片

解析:类似于芯片测试问题,使用分治策略。
算法设计思想:采用分治策略。若n<3,将剩下的硬币与之前比较拿走的硬币相比较,不等的就是不合格的硬币。否则,将n个硬币分成大致相等的3份,如果n%3!=0,则令两份少的相等,取两份相等的放到天平上,如果天平不平衡,说明不合格的硬币在这两堆之中,直接将这两堆合并再进行下一次的分组,否则,说明不合格的硬币在另外一堆,递归处理,直到n<3为止。
伪代码:
算法Coin(A,n) //A是n个硬币的集合

  1. k<- ⌊ n / 3 ⌋ \left \lfloor n/3\right \rfloor n/3
  2. 将A中的硬币分为X,Y,Z三个集合,使得|X|=|Y|=k,|Z|=n-2k
  3. if W(X)!=W(Y) //说明两堆硬币不相等
  4. then A<-X∪Y
  5. else A<- Z
  6. if n>2 then goto 1
  7. else 将A中的硬币与拿走的硬币比较,不等则是不合格的硬币

该算法的递推方程:
T ( n ) = T ( 2 n / 3 ) + O ( 1 ) T(n)=T(2n/3)+O(1) T(n)=T(2n/3)+O(1) 每一次划分都划分成了原问题规模的2/3,还需要加上划分的工作量
T ( 1 ) = 0 , T ( 2 ) = 1 T(1)=0,T(2)=1 T(1)=0,T(2)=1


15、设字符集S,其中8个字符A,B,C,D,E,F,G,H的频率是 1 100 , 1 100 , 2 100 , 3 100 , 5 100 , 8 100 , 13 100 , 21 100 \frac{1}{100},\frac{1}{100},\frac{2}{100},\frac{3}{100},\frac{5}{100},\frac{8}{100},\frac{13}{100},\frac{21}{100} 1001,1001,1002,1003,1005,1008,10013,10021,设计这8个字符的Hufffman树和编码
解析:为了方便画图,我们将上面的频率都乘100
算法设计与分析常见习题及详解_第12张图片


16、概述回溯算法的有关概念

  • 回溯算法(what)
    • 按照某种搜索策略搜索解空间得到解的一种技术。常用的搜索策略有深度优先、宽度优先、深宽结合、函数优先等等。
  • 基本思想:沿着一条向前走,能走则走,不能走就退回来,试着走其他路。以深度优先的方式遍历子集树。(在一棵具有全部可行解的树中进行深度优先搜索,解为叶子节点。在搜索的过程中,每到达一个节点,就判断以该节点为根的子树是否含有问题的解,若可以确定不含问题的解,则退回到上层父节点,继续下一步深度优先搜索过程)
    • 适用:求解搜索问题和优化问题
    • 搜索空间:树,节点对应部分解向量,可行解在叶子上
    • 搜索过程:采用系统的方法隐含遍历搜索树
    • 搜索策略:深度优先,宽度优先,函数优先,宽深结合等
    • 节点分支判定条件:满足约束条件——分支扩张解向量,不满足约束条件,回溯到该节点的父节点
    • 节点生成:动态生成
    • 存储:当前路径
  • 解空间(what)
    • 搜索问题的解所在的集合
  • 代价函数(what+why)
    • 计算位置:搜索树的节点
    • :极大化问题是以该点为根的子树所有可行解的值的上界(极小化问题为下界)
    • 性质:对极大化问题父节点代价不小于子节点的代价(极小化问题相反)
  • 界函数(what+why)
    • 含义:当前得到可行解的目标函数的最大值(极小化问题相反)
    • 初值:极大化问题初值为0(极小化问题为最大值)
    • 更新:得到更好的可行解时
  • 多米诺性质(what)——回溯算法适用条件
    • 在结点< x 1 , x 2 , . . . . x k x_1,x_2,....x_k x1,x2,....xk>处,P( x 1 , x 2 , . . . . x k x_1,x_2,....x_k x1,x2,....xk)为真(前k个解向量满足约束条件)
    • 多米诺性质:P( x 1 , x 2 , . . . . x k + 1 x_1,x_2,....x_{k+1} x1,x2,....xk+1)-》P( x 1 , x 2 , . . . . x k x_1,x_2,....x_k x1,x2,....xk),0
  • 回溯算法的设计步骤
    • 定义解向量和每个分量的取值范围:解向量为< x 1 , x 2 , . . . . x n x_1,x_2,....x_n x1,x2,....xn>,确定 x i x_i xi的取值集合为 X i X_i Xi,i=1,2,3,…n
    • 在< x 1 , x 2 , . . . . x k − 1 x_1,x_2,....x_{k-1} x1,x2,....xk1>确定如何计算 x k x_k xk取值集合 S k , S k ∈ X k S_k,S_k∈X_k Sk,SkXk
    • 确定结点儿子的排列顺序
    • 判断是否满足多米诺性质
    • 确定每个结点分支的约束条件
    • 确定搜索策略:深度优先,宽度优先等
    • 确定存储搜索路径的数据结构
  • 注意事项:在回溯函数体内,不能改变问题的状态,即进入函数前,状态是s,则完成函数后,状态也是s。回溯算法的使用前提是满足多米诺性质。

17、总结排序算法的复杂性

排序 最好时间复杂度 平均时间复杂度 最差时间复杂度 空间复杂度 是否稳定 算法比较优秀的情况
冒泡排序 O(n) O( n 2 n^2 n2) O( n 2 n^2 n2) O(1) 当待排序数组基本有序,个数较少
选择排序 O( n 2 n^2 n2) O( n 2 n^2 n2) O( n 2 n^2 n2) O(1) 与平均时间复杂度一样
快速排序 O(nlogn) O(nlogn) O( n 2 n^2 n2) O(logn)~O(n)
插入排序 O(n) O( n 2 n^2 n2) O( n 2 n^2 n2) O(1) 当待排序数组基本有序,个数较少
堆排序 O(nlogn) O(nlogn) O(nlogn) O(1)
归并排序 O(nlogn) O(nlogn) O(nlogn) O(n) 执行效率与要排序的原始数组的有序程度无关,所以其时间复杂度是非常稳定的,不管是最好情况、最坏情况,还是平均情况,时间复杂度都是O(nlogn).
希尔排序 O( n 1.3 n^{1.3} n1.3) O(nlogn)~O( n 2 n^2 n2) O( n 2 n^2 n2) O(1)

18、设计一个动态规划算法计算下面的数列中的F(n):
F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2),n>=2
算法设计与分析常见习题及详解_第13张图片
基本思想:将privious(F(n))的值保存起来,因为计算后面的F(n)需要用到前面计算的结果。

1. arr[0]<-0,arr[1]<-1;
2. for i<- 2 to n do
3. 	arr[i]<-arr[i-1]+arr[i-2];

19、设计一个算法,对于一个给定的包含n个整数的集合S和另一个给定的整数x,该算法可以在O(nlogn)时间内确定S中是否存在两个元素,使得它们的和恰为x
解析:由于算法的时间复杂度为O(nlogn),则可以很容易想到排序算法中有很多O(nlogn)的算法,如快速排序。
基本思路:可以使用快速排序算法对集合S进行从小到大的排序,令i=0,j=length(S)-1,即i和j分别指向集合S的首尾,比较S[i]+S[j]与x的大小,若S[i]+S[j]x,则j–,直到找到S[i]+S[j]=x或者i>j停止。
分析算法的时间复杂度:排序算法的时间复杂度为O(nlogn),遍历数组O(n),比较O(n),因此算法的复杂度为O(nlogn)+O(n)+O(n)-》O(nlogn),因此,满足题目要求。

#include <cstdio>
#include <cstdlib>
#include <cstring>
//快排 时间复杂度O(nlogn)
void quick_sort(int* arr, int l, int r) {
    if (l >= r) return;
    while (l < r) {
        int x = l, y = r;
        int z = arr[l];
        do {
            while (x <= y && arr[x] < z) x++;
            while (x <= y && arr[y] > z) y--;
            if (x <= y) {
                int temp = arr[x];
                arr[x] = arr[y];
                arr[y] = temp;
                x++, y--;
            }
        } while (x <= y);
        quick_sort(arr, l, y);
        l = x;
    }
}
//判断是否满足条件 O(n)时间复杂度
bool is_ok(int* A, int x, int len) {
	quick_sort(A, 0, len - 1);
	int i = 0, j = len - 1;
	while (i < j) {
		if (A[i] + A[j] == x) return true;
		else if (A[i] + A[j] > x) j--;
		else i++;
	}
	return false;
}

int main() {
	int A[8] = {3, 41, 52, 26, 38, 57, 9, 49};
	int x;
	while (scanf("%d", &x) != EOF) {
		printf("%d\n", is_ok(A, x, 8));
	}

	return 0;
}

20、利用差消法求递推方程
算法设计与分析常见习题及详解_第14张图片


21、分治策略的典型例子:芯片测试
有n片芯片,已知好芯片至少比坏芯片多1片,如何实现找出一片好芯片(要求使用最少的测试次数)。
算法设计与分析常见习题及详解_第15张图片
基本思想:将n片芯片分成 ⌊ n 2 ⌋ \left \lfloor \frac{n}{2}\right \rfloor 2n组,让每两两进行测试,如果测试结果为1好1坏或两个都是坏,则直接丢弃这一组,如果两个都报告好,那么从该组中随机选择一片。不断重复上述步骤。当n=3时,任取两片进行测试,报告1好1坏或2坏,都取未测试的芯片,若报告2好,则随机取一个。若n=2或n=1,随机取一片即为好芯片。
时间复杂度:O(n)
W ( n ) = W ( n / 2 ) + O ( n ) W(n)=W(n/2)+O(n) W(n)=W(n/2)+O(n)
W ( 3 ) = 1 , W ( 1 ) = W ( 2 ) = 0 W(3)=1,W(1)=W(2)=0 W(3)=1,W(1)=W(2)=0
伪代码:

1. k<-n
2. while k>3 do 
3. 	将芯片分成k/2//如有轮空芯片,单独测试,根据情况丢弃或保留
4.  for i<-1 to k/2 do 
5. 		if 2片好,则任取一片留下
6. 		else 2片同时丢弃
7. 	k<- 此时剩下的芯片数
8. if k=3
9. 	then 任取2片芯片测试
10.		if 2好,任取一片被测芯片
11.		else 取未测试的芯片
12.	if k=1或k=2,任取一片 

22、经典的分治例子:幂乘问题
输入:a为给定实数,n为自然数
输出: a n a^n an
该分治问题的设计思想:若n是偶数,则只要计算 a n / 2 a^{n/2} an/2就可以了,剩下的 a n / 2 a^{n/2} an/2可以直接照搬之前的结果。若n是奇数,则只需要计算 a n − 1 / 2 a^{n-1/2} an1/2就可以了,然后最后结果还要多乘一个a。
算法设计与分析常见习题及详解_第16张图片
时间复杂度: W ( n ) = Θ ( l o g n ) W(n)=\Theta(logn) W(n)=Θ(logn)
W ( n ) = W ( n / 2 ) + Θ ( 1 ) W(n)=W(n/2)+\Theta(1) W(n)=W(n/2)+Θ(1)


23、典型的动态规划问题:投资问题
5万元钱,4项目投资, f i ( x ) f_i(x) fi(x):将x元投给第i个项目的效益。求使得总效益最大的投资方案。
效益函数如下:
算法设计与分析常见习题及详解_第17张图片
解析:
k:对项目1,2,…k的投资
x:投资总钱数不超过x
F k ( x ) F_k(x) Fk(x):x元钱投给前k个项目的最大效益。
x k ( x ) x_k(x) xk(x)为当 F k ( x ) F_k(x) Fk(x)取最大值时, x k x_k xk的取值
因此,递推方程和边界条件为:
F k ( x ) = m a x { f k ( x k ) + F k − 1 ( x − x k ) } , k > 1 , 0 < = x k < = x F_k(x)=max\{ f_k(x_k)+F_{k-1}(x-x_k)\},k>1,0<=x_k<=x Fk(x)=max{fk(xk)+Fk1(xxk)},k>1,0<=xk<=x
F 1 ( x ) = f 1 ( x ) F_1(x)=f_1(x) F1(x)=f1(x)
当k=1时:
F 1 ( 0 ) = 0 , F 1 ( 1 ) = 11 , F 1 ( 2 ) = 12 , F 1 ( 3 ) = 13 , F 1 ( 4 ) = 14 , F 1 ( 5 ) = 15 F_1(0)=0,F_1(1)=11,F_1(2)=12,F_1(3)=13,F_1(4)=14,F_1(5)=15 F1(0)=0,F1(1)=11,F1(2)=12,F1(3)=13,F1(4)=14,F1(5)=15
当k=2时:
F 2 ( 0 ) = 0 , F 2 ( 1 ) = m a x { f 2 ( 0 ) + F 1 ( 1 ) , f 2 ( 1 ) + F 1 ( 0 ) } = 11 x 2 ( 1 ) = 0 F_2(0)=0,F_2(1)=max\{ f_2(0)+F_1(1),f_2(1)+F_1(0)\}=11x_2(1)=0 F2(0)=0,F2(1)=max{f2(0)+F1(1),f2(1)+F1(0)}=11x2(1)=0
F 2 ( 2 ) = m a x { f 2 ( 0 ) + F 1 ( 2 ) , f 2 ( 1 ) + F 1 ( 1 ) , f 2 ( 2 ) + F 1 ( 0 ) } = 12 , x 2 ( 2 ) = 0 F_2(2)=max\{ f_2(0)+F_1(2),f_2(1)+F_1(1),f_2(2)+F_1(0)\}=12,x_2(2)=0 F2(2)=max{f2(0)+F1(2),f2(1)+F1(1),f2(2)+F1(0)}=12,x2(2)=0
F 2 ( 3 ) = m a x { f 2 ( 0 ) + F 1 ( 3 ) , f 2 ( 1 ) + F 1 ( 2 ) , f 2 ( 2 ) + F 1 ( 1 ) , f 2 ( 3 ) + F 1 ( 0 ) } = 16 , x 2 ( 3 ) = 2 F_2(3)=max\{ f_2(0)+F_1(3),f_2(1)+F_1(2),f_2(2)+F_1(1),f_2(3)+F_1(0)\}=16,x_2(3)=2 F2(3)=max{f2(0)+F1(3),f2(1)+F1(2),f2(2)+F1(1),f2(3)+F1(0)}=16,x2(3)=2
F 2 ( 4 ) = m a x { f 2 ( 0 ) + F 1 ( 4 ) , f 2 ( 1 ) + F 1 ( 3 ) , f 2 ( 2 ) + F 1 ( 2 ) , f 2 ( 3 ) + F 1 ( 1 ) , f 2 ( 4 ) + F 1 ( 0 ) } = 21 , x 2 ( 4 ) = 3 F_2(4)=max\{ f_2(0)+F_1(4),f_2(1)+F_1(3),f_2(2)+F_1(2),f_2(3)+F_1(1),f_2(4)+F_1(0)\}=21,x_2(4)=3 F2(4)=max{f2(0)+F1(4),f2(1)+F1(3),f2(2)+F1(2),f2(3)+F1(1),f2(4)+F1(0)}=21,x2(4)=3
F 2 ( 5 ) = m a x { f 2 ( 0 ) + F 1 ( 5 ) , f 2 ( 1 ) + F 1 ( 4 ) , f 2 ( 2 ) + F 1 ( 3 ) , f 2 ( 3 ) + F 1 ( 2 ) , f 2 ( 4 ) + F 1 ( 1 ) , f ( 5 ) + F 1 ( 0 ) } = 26 , x 2 ( 5 ) = 4 F_2(5)=max\{ f_2(0)+F_1(5),f_2(1)+F_1(4),f_2(2)+F_1(3),f_2(3)+F_1(2),f_2(4)+F_1(1),f_(5)+F_1(0)\}=26,x_2(5)=4 F2(5)=max{f2(0)+F1(5),f2(1)+F1(4),f2(2)+F1(3),f2(3)+F1(2),f2(4)+F1(1),f(5)+F1(0)}=26,x2(5)=4
同理,当k=3,4的时候如此。
备忘录:
算法设计与分析常见习题及详解_第18张图片
因此,5万元分给4个项目的最大效益为61万元。每个项目的分配方案为:<1,0,3,1>
备忘录中有m行n列:时间复杂度分析:W(n)= O ( n m 2 ) O(nm^2) O(nm2)


24、动态规划求解背包问题
物品n种,每种的重量和价值分别为 w i , v i w_i,v_i wi,vi,如果背包最大限重为b,每种物品可以放多个,怎么选择放入的物品使得背包价值最大?
假设n=4,b=10,
v 1 = 1 , v 2 = 3 , v 3 = 5 , v 4 = 9 v_1=1,v_2=3,v_3=5,v_4=9 v1=1,v2=3,v3=5,v4=9
w 1 = 2 , w 2 = 3 , w 3 = 4 , w 4 = 7 w_1=2,w_2=3,w_3=4,w_4=7 w1=2,w2=3,w3=4,w4=7
解析
目标函数: m a x ∑ i = 1 n v i x i max\sum_{i=1}^nv_ix_i maxi=1nvixi
约束条件: ∑ i = 1 n w i x i < = b , x i ∈ N \sum_{i=1}^nw_ix_i<=b,x_i∈N i=1nwixi<=b,xiN
k:考虑对物品1,2,…k的选择
y:背包总重量不超过y
F k ( y ) F_k(y) Fk(y):表示前k种物品,总重不超过y背包达到的最大价值
F k ( y ) = m a x { F k − 1 ( y − w k ) + v k , F k − 1 ( y ) } F_k(y)=max\{ F_{k-1}(y-w_k)+v_k,F_{k-1}(y)\} Fk(y)=max{Fk1(ywk)+vk,Fk1(y)}
F 0 ( y ) = 0 , 0 < = y < = b , F k ( 0 ) = 0 , 0 < = k < = n F_0(y)=0,0<=y<=b,F_k(0)=0,0<=k<=n F0(y)=0,0<=y<=b,Fk(0)=0,0<=k<=n
F 1 ( y ) = ⌊ y / w 1 ⌋ v 1 , F k ( y ) = − ∞ , y < 0 F_1(y)=\left \lfloor y/w_1 \right \rfloor v_1,F_k(y)=-\infty,y<0 F1(y)=y/w1v1,Fk(y)=,y<0
算法设计与分析常见习题及详解_第19张图片
时间复杂度为O(nb)


25、动态规划之最长公共子序列问题
X:A B C B D A B
Y:B D C A B A
最长公共子序列为:B C B A ,长度为4
令X与Y的子序列 X i = < x 1 , x 2 . . . . x i > , Y j = < y 1 , y 2 , . . . . y j > X_i=,Y_j= Xi=<x1,x2....xi>,Yj=<y1,y2,....yj>
C [ i , j ] = 0 , 若 i = 0 或 j = 0 C[i,j]=0,若i=0或j=0 C[i,j]=0,i=0j=0
C [ i , j ] = 1 + C [ i − 1 , j − 1 ] , 若 i , j > 0 , x i = x j C[i,j]=1+C[i-1,j-1],若i,j>0,x_i=x_j C[i,j]=1+C[i1,j1],i,j>0,xi=xj
C [ i , j ] = m a x { C [ i − 1 , j ] , C [ i , j − 1 ] } , 若 i , j > 0 , x i ≠ x j C[i,j]=max\{ C[i-1,j],C[i,j-1]\},若i,j>0,x_i\not=x_j C[i,j]=max{C[i1,j],C[i,j1]},i,j>0,xi=xj
算法设计与分析常见习题及详解_第20张图片
时间复杂度:O(mn)


26、动态规划之最大字段和问题:
C [ i ] C[i] C[i]表示为以A[i]为最大子段结尾的最大子段和
递推方程:
C [ i ] = m a x { A [ i ] , A [ i ] + C [ i − 1 ] } , i = 1 , 2 , . . . n C[i]=max\{ A[i],A[i]+C[i-1]\},i=1,2,...n C[i]=max{A[i],A[i]+C[i1]},i=1,2,...n
C[1]=A[1],若A[1]>0
C[1]=0 否则
解: O P T ( A ) = m a x C [ i ] , 1 < = i < = n OPT(A)=max{C[i]},1<=i<=n OPT(A)=maxC[i],1<=i<=n
时间复杂度为O(n)


27、对于下列数组使用快速排序算法,写出每一次划分的结果。并简单描述快速排序的基本思想
在这里插入图片描述
快速排序的基本思想:(是一种分治策略)将待排序的数组经过一趟排序分成独立的两个部分,一个部分比关键字小,一个部分比关键字大,然后可以分别对这两部分的记录进行排序,以达到整个数组的有序。
第一次划分:2 1 3 4 8 7 6 5
第二次划分:1 2 3 4 5 7 6 8
第三次划分:1 2 3 4 5 7 6 8
第四次划分:1 2 3 4 5 6 7 8


28、在下面的有向图中应用算法Dijstra。假设顶点1是起始顶点。
算法设计与分析常见习题及详解_第21张图片
算法设计与分析常见习题及详解_第22张图片
从节点1出发到节点1,2,3,4,5的最短距离为0,2,5,11,10,14


29、各种关于算法的基本概念:

  • 算法的特点:确定性、有穷性、可行性、0到多个输入、1到多个输出。
  • 问题:所有实例构成的抽象描述(含参数和解的描述)

分治策略的基本思想:

  • 将原始问题划分或者归结为规模较小的子问题,每个子问题相互独立并且与原问题相同
  • 递归或迭代求解每个子问题
  • 将子问题的解综合得到原问题的解

使用动态优化算法的原则是:具有最优子结构性质(某个问题的最优解包含子问题的最优解。)

设计动态规划算法的主要步骤:

  • 问题具有最优子结构性质。
  • 构造最优值的递归关系表达式。
  • 最优值的算法描述。
  • 构造最优解。

动态规划算法的基本要素是最优子结构性质子问题重叠性质
贪心算法的基本要素是贪心选择性质最优子结构性质

请简述你对算法复杂性概念的认识:
算法复杂性是指算法运行所需要计算机资源的量。需要时间资源的量称为时间复杂性,需要的空间资源的量,称为空间复杂性。
时间复杂性和空间复杂性是衡量算法效率的两个重要指标。一般的,我们认为时间复杂度越小,算法的效率越高;空间复杂度越小,算法的效率越高。但是在实际中,我们很难保证一个算法既有好的时间复杂度又有好的空间复杂度,所以评判一个算法的好坏,还需要在具体环境中。若环境对空间的要求很苛刻,那么我们往往会牺牲时间换空间,反之亦如此。

在算法复杂性研究中,衡量输入问题的大小的常用方法有哪些?

  • 排序问题中,待排序数组元素的数目
  • 图的算法中,边或顶点的个数
  • 计算几何中,点、顶点、边、线段、或多边形数目
  • 矩阵预算中,矩阵的维数
  • 数论和密码学中,输入的比特数

最优算法的定义是什么?请举出一个最优算法的例子说明。
如果可以证明一个问题I的算法必然是 Ω ( f ( n ) ) Ω(f(n)) Ω(f(n))的,那么在 O ( f ( n ) ) O(f(n)) O(f(n))时间内解决问题I的算法称为问题I的最优算法。对n大小的数组排序的问题是 Ω ( n l o g n ) Ω(nlogn) Ω(nlogn),而归并排序算法的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),因此,归并排序是基于比较排序的最优算法。

请给出回溯算法的主要步骤和适用范围
回溯算法适用于搜索问题和优化问题。
解析
回溯算法的一般步骤:

  • 将解空间表示成一棵树(解空间树),求解问题就转换为在树T中搜索解对应的结点
  • 定义剪枝操作(考虑约束条件和目标值两方面)
  • 从树T的根节点开始,用深度优先法搜索该树,而跳过肯定不包含问题的解对应的节点的子树的搜索(剪枝),以提高效率。

请给出衡量算法性能的几个标准
正确性、易读性、健壮性、算法的时间复杂度和空间复杂度。

在算法复杂性研究中,基本运算的概念是什么?不同问题中常用的基本运算是什么?
解析:如果在一个算法中一个元运算具有最高频率,所有其他的元运算频率均在他的频度的常数倍内,则称这个元运算是基本运算。
常选取的基本运算有:

  • 在搜索和排序算法中,选取比较运算作为基本运算
  • 在矩阵乘法中,选取数乘运算作为基本运算
  • 在遍历一个链表中,选取设置或更新指针作为基本运算
  • 在图的遍历中,选取访问节点动作为基本运算

请简述你对时间复杂性渐进表示方法的常用符号及其含义
算法设计与分析常见习题及详解_第23张图片

你可能感兴趣的:(数据结构与算法,算法)