分治策略-算法导论笔记

本文深入探讨了分治策略的步骤,包括分解、解决和合并,并详细阐述了递归式的三种求解方法:代入法、递归树法和主方法。以最大子数组问题为例,展示了如何应用分治算法,并通过具体实例解析了如何用这些方法求解递归式,以确定算法的时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

分治策略

步骤

分解(Divide):将问题划分为一些子问题,子问题的形式与原问题一样,只是规模更小。(递归情况(Recursive case))

解决(Conquer):递归地求解子问题。如果子问题规模足够小,则停止递归,直接求解。(基本情况(Base case))

合并(Combine):将子问题的解组合成原问题的解。

递归式(recurrence)

T ( n ) = { Θ ( 1 ) , i f   n = 1 a T ( n / b ) + f ( n ) , i f   n > 1 (1) T(n)=\begin{cases} \Theta(1),if\space n=1\\ aT(n/b) + f(n), if\space n>1 \tag{1} \end{cases} T(n)={Θ(1),if n=1aT(n/b)+f(n),if n>1(1)

三种求解递归式的方法

  • 代入法:我们猜测一个界,然后用数学归纳法证明这个界是正确的。

  • 递归树法:将递归式转换成一棵树,其结点表示不同层次的递归调用产生的代价。然后采用边界和技术求解递归式。

  • 主方法:可求解形如(1)的递归式的界

    其中, a ≥ 1 , b > 1 , f ( n ) a \geq 1,b > 1,f(n) a1,b>1,f(n)是一个给定的函数。这种形式的递归式很常见,它刻画了这样一个分治算法:生成 a a a个子问题,每个子问题的规模是原问题规模的 1 / b 1/b 1/b,分解和合并共花费的时间为 f ( n ) f(n) f(n)


最大子数组问题

暴力求解算法

算法思想

只要确定头和尾即可 n n n 天共有 ( n 2 ) \begin{pmatrix} n \\ 2\end{pmatrix} (n2)种日期组合。因为 ( n 2 ) = Θ ( n 2 ) \begin{pmatrix} n \\ 2\end{pmatrix}=\Theta(n^2) (n2)=Θ(n2),所以这种方法运行的时间为 Θ ( n 2 ) \Theta (n^2) Θ(n2)

伪代码

	BruteForceMethod(A)
        maxVal = Integer.MIN_VALUE
    	for i = 0 to A.length - 1
            sum = 0
            for j = i to A.length - 1
                sum += A[i]
                if sum > maxVal
                    maxVal = sum

分治算法

算法思想

假设我们要寻找子数组 A [ l o w ] , … , A [ h i g h ] A[low], \dots ,A[high] A[low],,A[high]的最大子数组。将子数组划分为两个规模相等的子数组,然后只要求解子数组 A [ l o w ] , … , A [ m i d ] A[low],\dots,A[mid] A[low],,A[mid] A [ m i d + 1 ] , … , A [ h i g h ] A[mid+1],\dots,A[high] A[mid+1],,A[high]的最大子数组。 A [ l o w ] , … , A [ h i g h ] A[low], \dots ,A[high] A[low],,A[high]的最大子数组 A [ i ] , … , A [ j ] A[i],\dots,A[j] A[i],,A[j]是以下三种情况之一:

  • 完全位于子数组 A [ l o w ] , … , A [ m i d ] A[low],\dots,A[mid] A[low],,A[mid]
  • 完全位于子数组 A [ m i d + 1 ] , … , A [ h i g h ] A[mid+1],\dots,A[high] A[mid+1],,A[high]
  • 跨越了中点 m i d mid mid
伪代码

寻找跨越中点的子数组

	findMaxCrossingSubArray(A, low, mid, high)
        left-sum = Integer.MIN_VALUE
        sum = 0
        for i = mid - 1 downto low
            sum += A[i]
            if sum > left-sum
                left-sum = sum
                max-left = i
        right-sum = Integer.MIN_VALUE
        sum = 0
        for j = mid to high - 1
            sum += A[j]
            if sum > right-sum
                right-sum = sum
                max-right = j
        return (max-left, max-right, left-sum + right-sum)

分解

	findMaxSubArray(A, low, high)
        if low == high
            return (low, high, A[low])
        mid = (low + high) / 2
        (left-low, left-high, left-sum) = findMaxSubArray(A, low, mid)
        (right-low, right-high, right-sum) = findMaxSubArray(A, mid, high)
        (cross-low, cross-high, cross-sum) = findMAxCrossingSubArray(A, low, mid, high)
        if left-sum >= right-sum and left-sum >= cross-sum
            return (left-low, left-high, left-sum)
        if right-sum >= left-sum and right-sum >= cross-sum
            return (right-low, right-high, right-sum)
        return (cross-low, cross-high, cross-sum) 

分析

递归式

T ( n ) = { Θ ( 1 ) 若 n = 1 2 T ( n / 2 ) + Θ ( n ) 若 n > 1 (2) T(n)=\begin{cases} \Theta (1) 若n=1\\ 2T(n/2)+\Theta(n)若n>1 \end{cases} \tag{2} T(n)={Θ(1)n=12T(n/2)+Θ(n)n>1(2)

得到其时间复杂度为 T ( n ) = Θ ( n l o g n ) T(n)=\Theta(nlogn) T(n)=Θ(nlogn)

用代入法求解递归式

代入法求解步骤

  1. 猜测解的形式。
  2. 用数学归纳法求解解中的常数,并证明解是正确的。

例如,我们要确定下面递归式的上界:
T ( n ) = 2 T ( ⌊ n / 2 ⌋ ) + n T(n)=2T(\lfloor n/2 \rfloor)+n T(n)=2T(n/2)+n
猜测其解为: T ( n ) = O ( n l o g n ) T(n)=O(nlogn) T(n)=O(nlogn)。代入法要求证明恰当选择常数 c > 0 c>0 c>0,有 T ( n ) ≤ c n l o g n T(n) \leq cnlogn T(n)cnlogn

所以, T ( ⌊ n / 2 ⌋ ) ≤ c ⌊ n / 2 ⌋ l g ( ⌊ n / 2 ⌋ ) T(\lfloor n/2 \rfloor) \leq c\lfloor n/2 \rfloor lg(\lfloor n/2 \rfloor) T(n/2)cn/2lg(n/2),将其代入递归式,得到
T ( n ) ≤ 2 ( c ⌊ n / 2 ⌋ l g ( ⌊ n / 2 ⌋ ) ) + n ≤ c n l g ( n / 2 ) + n = c n l g n − c n l g 2 + n = c n l g n − c n + n ≤ c n l g n T(n) \leq 2(c\lfloor n/2 \rfloor lg(\lfloor n/2 \rfloor))+n\\ \leq cnlg(n/2)+n \\ =cnlgn-cnlg2+n \\ =cnlgn-cn+n\\ \leq cnlgn T(n)2(cn/2lg(n/2))+ncnlg(n/2)+n=cnlgncnlg2+n=cnlgncn+ncnlgn
只要, c ≥ 1 c\geq 1 c1,最后一步都会成立。

做出好的猜测

  • 遗憾的是,不存在通用的方法来猜测递归式正确的解。猜测要靠经验,偶尔还要创造力。

  • 另一种做出好的猜测的方法是先证明递归式较松的上界和下界,然后缩小不确定的范围。两边夹定理

微妙的细节

  • 有时候你可能正确的才出了递归式解的渐进界,但莫名其妙地在归纳证明时失败了,此时,如果修改猜测,减去一个低阶项,证明往往可以顺利进行。

  • 我们在归纳证明时一定要显式地证明与假设时的严格一致的形式。如当要证明: T ( n ) = O ( n ) T(n)=O(n) T(n)=O(n)时,需要显式证明 T ( n ) ≤ c n T(n) \leq cn T(n)cn

改变变量(换元)

例如,
T ( n ) = 2 T ( n ) + lg ⁡ n T(n)=2T(\sqrt {n})+\lg n T(n)=2T(n )+lgn
看起来很困难,但是,如果令 m = lg ⁡ n m=\lg n m=lgn,那么有
T ( 2 m ) = 2 T ( 2 m / 2 ) + m T(2^m)=2T(2^{m/2})+m T(2m)=2T(2m/2)+m
再令 S ( m ) = T ( 2 m ) S(m)=T(2^m) S(m)=T(2m),则
S ( m ) = 2 S ( m / 2 ) + m S(m)=2S(m/2)+m S(m)=2S(m/2)+m
变成了我们熟知的递归式,其时间复杂度为 S ( m ) = O ( m log ⁡ m ) S(m)=O(m\log m) S(m)=O(mlogm)

于是
T ( n ) = T ( 2 m ) = S ( m ) = O ( m log ⁡ m ) = O ( lg ⁡ n lg ⁡ lg ⁡ n ) T(n)=T(2^m)=S(m)=O(m\log m)=O(\lg n \lg \lg n) T(n)=T(2m)=S(m)=O(mlogm)=O(lgnlglgn)

用递归树求解递归式

例如,对于以下递归式
T ( n ) = 2 T ( n / 2 ) + n T(n)=2T(n/2)+n T(n)=2T(n/2)+n

A=cn
B=cn/2
C=cn/2
D=cn/4
E=cn/4
F=cn/4
G=cn/4

对其求和,
T ( n ) = c n + c n + ⋯ + c n ⏞ log ⁡ 2 n = c n log ⁡ 2 n = O ( n log ⁡ 2 n ) T(n)=\overbrace {cn+cn+\cdots+cn}^{\log_2 n}=cn\log_2n=O(n\log_2 n) T(n)=cn+cn++cn log2n=cnlog2n=O(nlog2n)

用主方法求解递归式

考虑如下形式的递归式:

T ( n ) = a T ( n / b ) + f ( n ) 其 中 , a ≥ 1 , b > 1 T(n)=aT(n/b)+f(n)\\ 其中,a\geq 1,b>1 T(n)=aT(n/b)+f(n),a1,b>1

主定理

**令 a ≥ 1 a\geq 1 a1 b > 1 b>1 b>1,是常数, f ( n ) f(n) f(n)是一个函数, T ( n ) T(n) T(n)**是定义在非负整数上的递归式:
T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n)


其中我们将n/b解释为 ⌊ n / b ⌋ \lfloor n/b \rfloor n/b ⌈ n / b ⌉ \lceil n/b \rceil n/b.那么 T ( n ) T(n) T(n)有如下渐进界:

  1. 若对某个常数 ϵ > 0 \epsilon > 0 ϵ>0 f ( n ) = O ( n log ⁡ b a − ϵ ) f(n)=O(n^{\log_b {a-\epsilon}}) f(n)=O(nlogbaϵ),则 T ( n ) = Θ ( n log ⁡ b a ) T(n)=\Theta(n^{\log_b a}) T(n)=Θ(nlogba)
  2. f ( n ) = Θ ( n log ⁡ b a ) f(n)=\Theta(n^{\log_b a}) f(n)=Θ(nlogba),则 T ( n ) = Θ ( n log ⁡ b a lg ⁡ n ) T(n)=\Theta(n^{\log_b a} \lg n) T(n)=Θ(nlogbalgn)
  3. 若对某个常数 ϵ > 0 \epsilon > 0 ϵ>0 f ( n ) = Ω ( n log ⁡ b a + ϵ ) f(n)=\Omega(n^{\log_b {a+\epsilon}}) f(n)=Ω(nlogba+ϵ),且对某个常数 c < 1 c<1 c<1和所有足够大的 n n n a f ( n / b ) ≤ c f ( n ) af(n/b)\leq cf(n) af(n/b)cf(n),则 T ( n ) = Θ ( f ( n ) ) T(n)=\Theta (f(n)) T(n)=Θ(f(n))

使用主方法

  1. 例1
    T ( n ) = 9 T ( n / 3 ) + n T(n)=9T(n/3)+n T(n)=9T(n/3)+n
    对于这个递归式, a = 9 , b = 3 , f ( n ) = n a=9, b=3,f(n)=n a=9,b=3,f(n)=n,因此 n log ⁡ b a = n log ⁡ 3 9 = Θ ( n 2 ) n^{\log_b a}=n^{\log_3 9}=\Theta(n^2) nlogba=nlog39=Θ(n2)。由于 f ( n ) = O ( n log ⁡ 3 9 − ϵ ) f(n)=O(n^{\log_3 {9-\epsilon}}) f(n)=O(nlog39ϵ),其中, ϵ = 1 \epsilon = 1 ϵ=1,由情况1,从而得到解 T ( n ) = Θ ( n 2 ) T(n)=\Theta(n^2) T(n)=Θ(n2)

  2. 例2
    T ( n ) = 3 T ( n / 4 ) + n lg ⁡ n T(n)=3T(n/4)+n\lg n T(n)=3T(n/4)+nlgn
    对于这个递归式, a = 3 , b = 4 , f ( n ) = n lg ⁡ n a=3,b=4,f(n)=n\lg n a=3,b=4,f(n)=nlgn,因此 n log ⁡ b a = n log ⁡ 4 3 = O ( n 0.793 ) n^{\log_b a}=n^{\log_4 3}=O(n^{0.793}) nlogba=nlog43=O(n0.793),由于 f ( n ) = Ω ( n log ⁡ 4 3 + ϵ ) f(n)=\Omega(n^{\log_4 {3+\epsilon}}) f(n)=Ω(nlog43+ϵ),其中, ϵ ≈ 0.2 \epsilon \approx 0.2 ϵ0.2.当n足够大时,对于 c = 3 / 4 , a f ( n / b ) = 3 ( n / 4 ) lg ⁡ ( n / 4 ) ≤ ( 3 / 4 ) n lg ⁡ n = c f ( n ) c=3/4,af(n/b)=3(n/4)\lg(n/4) \leq (3/4)n\lg n=cf(n) c=3/4,af(n/b)=3(n/4)lg(n/4)(3/4)nlgn=cf(n)。因此满足正则条件,根据情况3,得到解 T ( n ) = Θ ( n lg ⁡ n ) T(n)=\Theta(n\lg n) T(n)=Θ(nlgn)

  3. 例3
    T ( n ) = T ( 2 n / 3 ) + 1 T(n)=T(2n/3)+1 T(n)=T(2n/3)+1
    对于这个递归式, a = 1 , b = 2 / 3 , f ( n ) = 1 a=1,b=2/3,f(n)=1 a=1,b=2/3,f(n)=1,因此 n log ⁡ b a = n l o g 3 / 21 = n 0 = 1 n^{\log_b a}=n^{log_3/2{1}}=n^0=1 nlogba=nlog3/21=n0=1,由于 f ( n ) = Θ ( n log ⁡ b a ) = Θ ( 1 ) f(n)=\Theta(n^{\log_b a})=\Theta(1) f(n)=Θ(nlogba)=Θ(1),因此由情况2,得到解为: T ( n ) = Θ ( lg ⁡ n ) T(n)=\Theta(\lg n) T(n)=Θ(lgn)

)n\lg n=cf(n) 。 因 此 满 足 正 则 条 件 , 根 据 情 况 3 , 得 到 解 。因此满足正则条件,根据情况3,得到解 3T(n)=\Theta(n\lg n)$

  1. 例3
    T ( n ) = T ( 2 n / 3 ) + 1 T(n)=T(2n/3)+1 T(n)=T(2n/3)+1
    对于这个递归式, a = 1 , b = 2 / 3 , f ( n ) = 1 a=1,b=2/3,f(n)=1 a=1,b=2/3,f(n)=1,因此 n log ⁡ b a = n l o g 3 / 21 = n 0 = 1 n^{\log_b a}=n^{log_3/2{1}}=n^0=1 nlogba=nlog3/21=n0=1,由于 f ( n ) = Θ ( n log ⁡ b a ) = Θ ( 1 ) f(n)=\Theta(n^{\log_b a})=\Theta(1) f(n)=Θ(nlogba)=Θ(1),因此由情况2,得到解为: T ( n ) = Θ ( lg ⁡ n ) T(n)=\Theta(\lg n) T(n)=Θ(lgn)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值