算法导论习题—摊还时间代价分析、栈实现队列、贪心算法近似比、集合覆盖问题

算法导论习题—摊还时间代价分析、栈实现队列、贪心算法近似比、集合覆盖问题_第1张图片

在执行的 n n n个操作中,有至多 ⌈ l g n ⌉ ⌈lg n⌉ lgn个操作的次序是 2 2 2的幂,这些操作的次序(即代价)如下
1 , 2 , 4 , 8 , ⋅ ⋅ ⋅ , 2 ⌈ l g n ⌉ 1, 2, 4, 8, · · · , 2 ⌈lg n⌉ 1,2,4,8,,2lgn
n n n个操作的总代价为
T = ∑ k = 0 ⌈ l g n ⌉ 2 k + ( n − ⌈ l g n ⌉ ) × 1 = 2 ⌈ l g n ⌉ + 1 − 1 + ( n − ⌈ l g n ⌉ ) ≤ 2 lg ⁡ n + 2 + n − l g n = 3 l g n + n \begin{aligned} T&=\sum^{⌈lg n⌉}_{k=0}2^k + (n − ⌈lg n⌉) × 1\\ &=2^{⌈lg n⌉+1} − 1 + (n − ⌈lg n⌉)\\ &≤2^{\lg n+2} + n − lg n\\ &=3 lg n + n \end{aligned} T=k=0lgn2k+(nlgn)×1=2lgn+11+(nlgn)2lgn+2+nlgn=3lgn+n
因此每个操作的摊还代价是 O ( 3 lg ⁡ n + n n ) = O ( 1 ) O ( \cfrac{3 \lg n + n }n ) = O(1) O(n3lgn+n)=O(1)的。

在这里插入图片描述

当操作次序是 2 2 2的幂时,为其赋 4 4 4的摊还代价,否则为其赋 2 2 2的摊还代价,则每一个不为 2 2 2 的幂的操作均会提供 1 1 1的信用以支付差额,对于一 个 n n n个操作组成的操作序列,有
4 × ⌈ lg ⁡ n ⌉ + 2 × ( n − ⌈ lg ⁡ n ⌉ ) = 2 × ⌈ lg ⁡ n ⌉ + 2 n ≤ 3 lg ⁡ n + n ≤ ∑ k = 0 ⌈ l g n ⌉ 2 k + ( n − ⌈ lg ⁡ n ⌉ ) × 1 \begin{aligned} &4×⌈\lg n⌉+2×(n−⌈\lg n⌉) \\ &=2×⌈\lg n⌉+2n\\ &≤3\lg n+n\\ &≤\sum^{⌈lg n⌉}_{k=0}2^k+(n−⌈\lg n⌉)×1 \end{aligned} 4×lgn+2×(nlgn)=2×lgn+2n3lgn+nk=0lgn2k+(nlgn)×1
每个操作的摊还代价都是常数,因此摊还代价都为 O ( 1 ) O(1) O(1)

在这里插入图片描述

定义势函数
Φ P h i ( D i ) = { 0 ,                          i = 0 1 ,                          i = 1 lg ⁡ i + 1 ,                i = 2 ⌊ lg ⁡ i ⌋ ⌊ lg ⁡ i ⌋ + k ,            i = 2 ⌊ lg ⁡ i ⌋ + k ΦPhi(D_i) =\left\{ \begin{aligned} & 0, \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ i = 0\\ &1, \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ i = 1\\ & \lg i + 1, \ \ \ \ \ \ \ \ \ \ \ \ \ \ i = 2^{⌊\lg i⌋}\\ & ⌊\lg i⌋ + k, \ \ \ \ \ \ \ \ \ \ i = 2^{⌊\lg i⌋} + k \end{aligned} \right. ΦPhi(Di)=0,                        i=01,                        i=1lgi+1,              i=2lgilgi+k,          i=2lgi+k

则对任意的 i , Φ ( D i ) ≥ 0 i,Φ(D_i) ≥ 0 iΦ(Di)0,且
Φ ( D i ) − Φ ( D i − 1 ) = { 1 − i ,          i = 2 ⌊ lg ⁡ i ⌋ 1 ,                i = 2 ⌊ lg ⁡ i ⌋ + k Φ(D_i) − Φ(D_{i−1}) =\left\{ \begin{aligned} & 1-i, \ \ \ \ \ \ \ \ i = 2^{⌊\lg i⌋}\\ & 1, \ \ \ \ \ \ \ \ \ \ \ \ \ \ i = 2^{⌊\lg i⌋} + k \end{aligned} \right. Φ(Di)Φ(Di1)={1i,        i=2lgi1,              i=2lgi+k
所以:
∑ i = 1 n c ^ = ∑ i = 1 n 1 = n \sum^n_{i=1}\hat{c}=\sum^n_{i=1}1=n i=1nc^=i=1n1=n
因此每个操作的摊还代价是 O ( 1 ) O(1) O(1)

在这里插入图片描述

使用两个栈实现队列,将两个栈记为左右栈。

ENQUEUE \text{ENQUEUE} ENQUEUE:直接对左栈进行 push \text{push} push将元素入队

DEQUEUE \text{DEQUEUE} DEQUEUE:如果右栈非空,对右栈进行 pop \text{pop} pop。如果右栈为空,做一个迭代:把左栈元素 pop \text{pop} pop出来, push \text{push} push进右栈,直到左栈为空,再执行 DEQUEUE \text{DEQUEUE} DEQUEUE

FIND-MIN \text{FIND-MIN} FIND-MIN:在左右栈基础上再加一个辅助栈,用于记录最小值。每次有元素入左栈时,判断辅助栈为空或辅助栈的栈顶元素比入栈元素更大,则将该元素压入辅助栈中,否则将辅助栈的栈顶元素重复压入辅助栈。左栈需要弹出元素时,辅助栈需要同步弹出栈顶元素。取最小值时,直接将栈顶元素弹出,返回值即最小值。

摊还分析:

C i C_i Ci为第 i i i个操作的代价(假定每个操作的代价为 1 1 1)设每次操作的势能 D(i)=2* \text{D(i)=2*} D(i)=2*左栈元素个数,设左栈元素个数为 k k k

ENQUEUE:Ci+D(i)-D(i-1)=1+2*(k+1-k)=3 \text{ENQUEUE:Ci+D(i)-D(i-1)=1+2*(k+1-k)=3} ENQUEUECi+D(i)-D(i-1)=1+2*(k+1-k)=3 k + 1 k+1 k+1表示入队后的元素,所以入队摊还时间复杂度为 O ( 1 ) O(1) O(1)

DEQUEUE \text{DEQUEUE} DEQUEUE

  1. 如果右栈非空,左栈有 k k k个元素: Ci+D(i)-D(i-1)=1+2(k-k)=1 \text{Ci+D(i)-D(i-1)=1+2(k-k)=1} Ci+D(i)-D(i-1)=1+2(k-k)=1
  2. 如果右栈为空,左栈有 k k k个元素: Ci+D(i)-D(i-1)=2k+1+2(0-k)=1 \text{Ci+D(i)-D(i-1)=2k+1+2(0-k)=1} Ci+D(i)-D(i-1)=2k+1+2(0-k)=1,其中 2 k 2k 2k为左栈弹出元素数+右栈压入元素数, 1 1 1表示出队一个元素,所以出队摊还时间复杂度为 O ( 1 ) O(1) O(1)

FIND-MIN \text{FIND-MIN} FIND-MIN: 使用聚合法分析,取最小值实际上是对单个辅助栈的操作,考虑整个栈的 n n n个操作,一个对象压入栈后,至多弹出一次,则对该栈的 n n n PUSH、POP、MULTIPOP \text{PUSH、POP、MULTIPOP} PUSHPOPMULTIPOP的操作序列,代价至多是 O ( n ) O(n) O(n),一个操作的平均时间为 O ( n ) / n = 1 O(n)/n=1 O(n)/n=1,所以摊还复杂度为 O ( 1 ) O(1) O(1)

算法导论习题—摊还时间代价分析、栈实现队列、贪心算法近似比、集合覆盖问题_第2张图片

每次迭代添加包含未覆盖元素最多的集合, 直到满足全覆盖条件,时间复杂度为多项式时间 Θ ( k lg ⁡ n ) \Theta(k\lg n) Θ(klgn)

假设全集 S S S包含 n n n个元素,最优覆盖包含 k k k个子集合。那么我们使用的贪心算法最多会选择 k ln ⁡ n + 1 k\ln n+1 klnn+1个子集。
证明:

  1. u j u_j uj:在贪心算法第 j j j次迭代还没有被覆盖的元素个数

  2. O P T OPT OPT:最优解

  3. k k k个最优集合必定可覆盖住该 u j u_j uj个元素,故最优集合中至少有一个集合包含至少 u j k \cfrac{u_j}k kuj个元素

  4. 使用贪心算法后,我们可以递推得到
    u j + 1 ≤ u j − u j k = u j ( 1 − 1 k ) ≤ u j − 1 ( 1 − 1 k ) ( 1 − 1 k ) ≤ … ≤ u 0 ( 1 − 1 k ) j + 1 = n ( 1 − 1 k ) j + 1 u_{j+1}\le u_j-\frac{u_j}k = u_j(1-\frac{1}k)\le u_{j-1}(1-\frac{1}k)(1-\frac{1}k)\le…\le u_0(1-\frac{1}k)^{j+1}=n(1-\frac{1}k)^{j+1} uj+1ujkuj=uj(1k1)uj1(1k1)(1k1)u0(1k1)j+1=n(1k1)j+1
    所以 u j + 1 ≤ n ( 1 − 1 k ) j + 1 u_{j+1}\le n(1-\frac{1}k)^{j+1} uj+1n(1k1)j+1

  5. lim ⁡ x → + ∞ ( 1 + x n ) n = e x \displaystyle\lim_{x \rightarrow + \infty}(1 + \frac{x}{n})^n = e^x x+lim(1+nx)n=ex,即存在这样一个式子 1 − x < = e − x 1-x <= e^{-x} 1x<=ex对所有的 x x x都成立
    所以
    u j ≤ u 0 ( 1 − 1 k ) j < u 0 ( e − 1 k ) j = n e − j k ( 1 − 1 k ) j = ( ( 1 − 1 k ) k ) j k ≤ e − j k n ⋅ e − j k ≤ 1 ⇔ e − j k ≤ n − 1 ⇔ − j k ≤ − ln ⁡ n ⇔ j ≥ k ln ⁡ n \begin{aligned} &u_j \le u_0(1-\frac{1}k)^j < u_0(e^{-{\frac{1}k}})^j = ne^{-{\frac{j}k}}\\ &(1-\frac{1}k)^j=((1-\frac{1}k)^k)^\frac{j}k\le e^{-\frac{j}k}\\ &n·e^{-\frac{j}k}\le 1\Leftrightarrow e^{-\frac{j}k}\le n^{-1}\Leftrightarrow -\frac{j}k \le-\ln n\Leftrightarrow j\ge k\ln n \end{aligned} uju0(1k1)j<u0(ek1)j=nekj(1k1)j=((1k1)k)kjekjnekj1ekjn1kjlnnjklnn
    j = k ln ⁡ n j=k\ln n j=klnn,结果等于 1 1 1,也就是说没有其他的元素剩下了,此时 ( 1 − 1 k ) k ln ⁡ n ≤ e − ln ⁡ n (1-\frac{1}k)^{k\ln n}\le e^{-\ln n} (1k1)klnnelnn O P T ≥ k ≥ O P T ⋅ ( 1 − ( 1 − 1 k ) k ) ≥ 1 − 1 e OPT\ge k\ge OPT·(1-(1-\frac{1}k)^k)\ge 1-\frac{1}e OPTkOPT(1(1k1)k)1e1,所以近似比为 1 − ( 1 − 1 k ) k ≥ 1 − 1 e 1-(1-\frac{1}k)^k\ge 1-\frac{1}e 1(1k1)k1e1,则对于一个含有 k ln ⁡ n + 1 k\ln n+1 klnn+1个子集的集合覆盖, k ln ⁡ n + 1 ∈ Θ ( k ⋅ ln ⁡ n ) = Θ ( k lg ⁡ n ) k\ln n+1∈\Theta(k·\ln n)=\Theta(k\lg n) klnn+1Θ(klnn)=Θ(klgn)

算法导论习题—摊还时间代价分析、栈实现队列、贪心算法近似比、集合覆盖问题_第3张图片

​ 当我们选择一个集合之后,删除已经被覆盖的元素。然后我们选择每个单位成本最小的集合直到覆盖所有元素。本质上每次选择覆盖未覆盖元素最多的集合。

C C C:代表到目前为止涵盖的元素集

cost effectiveness , or α \text{cost effectiveness , or α} cost effectiveness , or α:每个新覆盖节点的平均成本

​ 伪代码:

Greedy Method:
	Initial C
	While C != U:
		Find the set Si whose cost effectiveness is the smallest
		then Set C = C∪Si 
        Let α= wi/|Si-C|
		For	each e∈Si-C : Set price(e) = α
    end While
	Output Selected sets

我们每次选取的都是 w i S i − C \cfrac{w_i}{S_i-C} SiCwi最小的集合 S i S_i Si,即每次新添的集合 S i S_i Si的新增覆盖率相对于 cost \text{cost} cost值都是最大的,从而实现局部最优。
选择的集合按照先后顺序为 S 1 , S 2 , … , S m S_1 , S _2 , … , S _m S1,S2,,Sm

n i n _i ni 是选择 S i S_i Si时,其覆盖的新元素个数。

元素被覆盖的顺序 e 1 , e 2 , … , e n e_1,e_2,…,e _n e1,e2,,en

S j S_j Sj第一次覆盖新元素 e k e_k ek

C 1 , . . . C_1,... C1,...是最优覆盖中的部分集合,覆盖了 e k , … , e n , n i ′ e_ k , … , e _n,n _i' ek,,enni 是其覆盖的对应元素个数。不仅仅是 e k , … , e n e_ k ,…,e_ n ek,,en 中的元素。

  1. ∑ i n i ′ ≥ n − k + 1 , ∑ i c o s t ( C i ) ≤ O P T \sum_i n_i'\ge n-k+1, \sum_i cost(C_i)\leq OPT inink+1,icost(Ci)OPT,因为 C i , . . . C_ i , . . . Ci,...也可能覆盖了其他元素,是从最优覆盖中选择的部分集合。
  2. C 1 , . . . . C_1 ,.... C1,....没有与 S 1 , . . . S j − 1 S_1,...S_{j-1} S1,...Sj1重复的。假设某个 C i C_i Ci S 1 , . . . S j − 1 S_1,...S_{j-1} S1,...Sj1中,则 e k e_k ek之后的元素会被某个 S i ( i ∈ [ 1 , j − 1 ] ) S_i(i\in[1,j-1]) Si(i[1,j1])覆盖,矛盾。
  3. ∑ i c o s t ( C i ) ∑ i n i ′ ≤ O P T n − k + 1 ⟹ \cfrac{\sum_i cost(C_i) }{\sum_i n_i'}≤ \cfrac{O P T}{n − k + 1}\Longrightarrow iniicost(Ci)nk+1OPT存在某个 c o s t ( C i ) n i ′ ≤ O P T n − k + 1 \cfrac{cost(C_i)}{n_i′}≤ \cfrac{O P T}{n − k + 1} nicost(Ci)nk+1OPT
  4. 由贪心算法选出的 c o s t ( S j ) n j ≤ c o s t ( C i ) n i ′ \cfrac{cost(S_j)}{n_j}≤ \cfrac{cost(C_i)}{n_i′} njcost(Sj)nicost(Ci)
  5. 对于每个 k k k都存在满足 3 3 3 4 4 4 C i C_i Ci
  6. 每个点被覆盖的代价 c o s t ( e k ) ≤ c o s t o p t ( S ) n − k + 1 cost(e_k)\le \frac {cost_{opt}(S)}{n-k+1} cost(ek)nk+1costopt(S),所以在整个贪心过程中的总代价为 ∑ c o s t ( e k ) ≤ ( 1 + 1 2 + 1 3 + ⋅ ⋅ ⋅ 1 n ) ⋅ c o s t o p t = H n ⋅ c o s t o p t \sum cost(e_k)\le(1+\frac12+\frac13+···\frac1n)·cost_{opt} =H_n·cost_{opt} cost(ek)(1+21+31+n1)costopt=Hncostopt
  7. ∑ k c o s t ( e k ) ≤ ∑ k c o s t ( C i ) n i ′ ≤ ∑ k O P T n − k + 1 ∼ ln ⁡ n ⋅ O P T \sum_kcost(e_k)\leq \sum_k\cfrac{cost(C_i)}{n_i′} \leq \sum_k\cfrac{O P T}{n − k + 1}∼\ln n·OPT kcost(ek)knicost(Ci)knk+1OPTlnnOPT.

所以近似比为 ln ⁡ n \ln n lnn

你可能感兴趣的:(算法,数据结构,笔记,算法,java,人工智能)