【算法导论】【笔记/习题解】第四章:分治策略

概述

第四章围绕分治策略核心思想是将复杂问题拆解为规模更小的子问题,递归求解子问题后合并结果,同时系统讲解了递归式的三种求解方法(代入法、递归树法、主方法),本章目标是让掌握 “设计分治算法→建立递归式→求解递归式” 的流程,为后续复杂算法的学习奠定基础。

笔记

4.1 最大子数组问题

1. 问题背景与转化
  • 原始问题:给定股票连续 n 天的价格数组,需选择 “买入日” 和 “卖出日”(买入在前),最大化收益(卖出价 - 买入价)。若所有价格递减,收益为最大负差值(即只买一天再卖出,选择亏损最小的)。
  • 问题转化:将价格数组P[0..n-1]转化为价格变化数组A[1..n-1]A[i] = P[i] - P[i-1]),则原问题等价于 “在A中找连续非空子数组,使其和最大”—— 即最大子数组问题
2. 分治解法

对于子数组A[low..high],其最大子数组必属于以下三类之一:

  1. 完全位于左子数组A[low..mid]中;
  2. 完全位于右子数组A[mid+1..high]中;
  3. 跨越中点mid,即包含A[mid]A[mid+1]
3. 子程序与伪代码
(1)分治找最大子数组:FIND-MAX-SUBARRAY(A, low, mid, high)
  • 功能:找到最大子数组,返回其左右边界和总和。
  • 逻辑
    • mid向左扫描,找以mid为终点的最大子数组A[left..mid],记录左边界max-left和总和left-sum
    • mid+1向右扫描,找以mid+1为起点的最大子数组A[mid+1..right],记录右边界max-right和总和right-sum
    • 合并两者,总和为left-sum + right-sum,边界为(max-left, max-right)
  • 时间复杂度Θ(n)(左右扫描各遍历n/2个元素,总次数为n)。
(2)递归找最大子数组:FIND-MAXIMUM-SUBARRAY(A, low, high)
  • 功能:递归求解A[low..high]的最大子数组,返回边界和总和。
  • 伪代码核心步骤
if low == high: return (low, high, A[low]) 


mid = floor((low + high)/2)

 (left-low, left-high, left-sum) = FIND-MAXIMUM-SUBARRAY(A, low, mid)  // 左子问题

 (right-low, right-high, right-sum) = FIND-MAXIMUM-SUBARRAY(A, mid+1, high)  // 右子问题

 (cross-low, cross-high, cross-sum) = FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)  //跨越子问题


比较left-sum、right-sum、cross-sum,返回最大者对应的边界和总和

时间复杂度Θ(nlgn)

4.2 矩阵乘法的 Strassen 算法

1. 背景:普通矩阵乘法的局限性
  • 普通算法SQUARE-MATRIX-MULTIPLY(A, B),对n×n矩阵AB,结果C的元素C[i][j] = Σₖ₌₁ⁿ A[i][k]·B[k][j],需次标量乘法,时间复杂度Θ(n³)
  • 分治尝试:将A、B、C各分为 4 个n/2×n/2子矩阵,递归计算 8 次n/2×n/2矩阵乘法,时间复杂度仍为T(n) = 8T(n/2) + Θ(n²) = Θ(n³),无优化。
2. Strassen 算法的核心:减少递归调用次数

Strassen 算法通过7 次递归调用(而非 8 次)和10 次中间矩阵加减,将时间复杂度降至Θ(n^lg7) ≈ Θ(n².81),突破Θ(n³)的壁垒。

3. Strassen 算法四步骤(n为 2 的幂)
(1)分解(Θ(1)

A、B、C各分为 4 个n/2×n/2子矩阵:A = [[A₁₁, A₁₂], [A₂₁, A₂₂]]B = [[B₁₁, B₁₂], [B₂₁, B₂₂]]C = [[C₁₁, C₁₂], [C₂₁, C₂₂]]

(2)创建中间矩阵(Θ(n²)

生成 10 个n/2×n/2矩阵S₁~S₁₀,存储子矩阵的加减结果:S₁=B₁₂-B₂₂S₂=A₁₁+A₁₂S₃=A₂₁+A₂₂S₄=B₂₁-B₁₁S₅=A₁₁+A₂₂S₆=B₁₁+B₂₂S₇=A₁₂-A₂₂S₈=B₂₁+B₂₂S₉=A₁₁-A₂₁S₁₀=B₁₁+B₁₂

(3)递归乘法(7T(n/2)

计算 7 个n/2×n/2矩阵积P₁~P₇P₁=A₁₁·S₁P₂=S₂·B₂₂P₃=S₃·B₁₁P₄=A₂₂·S₄P₅=S₅·S₆P₆=S₇·S₈P₇=S₉·S₁₀

(4)合并结果(Θ(n²)

通过P₁~P₇的加减得到C的子矩阵:C₁₁=P₅+P₄-P₂+P₆C₁₂=P₁+P₂C₂₁=P₃+P₄C₂₂=P₅+P₁-P₃-P₇

4. 时间复杂度分析
  • 递归式T(n) = 7T(n/2) + Θ(n²)
  • 求解:(f(n)=Θ(n²) = O(n^(lg7 - ε))ε≈0.8),故T(n)=Θ(n^lg7)

4.3 代入法求解递归式

代入法是求解递归式的基础方法,核心是 “猜测解的形式→用数学归纳法验证”,适用于所有递归式,但依赖合理的猜测。

1. 两步流程
(1)猜测解的形式
  • 参考已知递归式:如T(n)=2T(n/2)+n与归并排序递归式类似,猜测解为O(nlg n)
  • 先证松的界:若不确定,先证T(n)=O(n²),再缩小到O(nlg n)
  • 改变变量:对复杂递归式(如T(n)=2T(√n)+lg n),令m=lg n,转化为T(2ᵐ)=2T(2^(m/2))+m,再猜测S(m)=T(2ᵐ)=O(mlg m),回代得T(n)=O(lg n · lg lg n)
(2)归纳证明
  • 步骤

    1. 确定归纳假设:假设对所有m<nT(m) ≤ c·g(m)g(m)为猜测的解);
    2. 代入递归式:证明T(n) ≤ c·g(n),需确定常数c的取值;
    3. 验证基本情况:确保n足够小时(如n=1,2),T(n) ≤ c·g(n)
  • 示例:证明T(n)=2T(⌊n/2⌋)+n ≤ c·nlg nc≥1):归纳假设:对m=⌊n/2⌋T(⌊n/2⌋) ≤ c·⌊n/2⌋·lg(⌊n/2⌋);代入递归式:T(n)≤2⋅c⋅⌊n/2⌋⋅lg(⌊n/2⌋)+n≤2⋅c⋅(n/2)⋅lg(n/2)+n=c⋅n(lgn−1)+n=c⋅nlgn−c⋅n+n当c≥1时,-c·n + n ≤0,故T(n) ≤ c·nlg n,得证。

4.4 递归树法求解递归式:可视化拆解

递归树将递归式转化为 “树结构”,每个节点代表子问题的代价,子节点对应递归调用的代价,叶节点对应基本情况的代价。通过计算树的总代价,直接得到递归式的界(常用于生成猜测,再用代入法验证)。

1. 构建与计算步骤
  1. 根节点:代价为f(n)(分解 + 合并代价),子节点为aT(n/b)a为子问题数,n/b为子问题规模);
  2. 中间层:第j层的每个节点代价为f(n/bʲ),共个节点,总代价为aʲ·f(n/bʲ)
  3. 叶节点:当n/bʲ=1j=log_b n)时,节点代价为Θ(1),共a^(log_b n)=n^(log_b a)个节点,总代价为Θ(n^(log_b a))
  4. 总代价:求和所有层的代价,得到T(n) = Θ(n^(log_b a)) + Σⱼ₌₀^(log_b n -1) aʲ·f(n/bʲ)
2. 示例分析
(1)递归式T(n)=3T(⌊n/4⌋)+Θ(n²)
  • 递归树构建
    • 根节点(j=0):代价c·n²,3 个子节点(a=3),规模n/4
    • 第 1 层(j=1):每个节点代价c·(n/4)²,3 个节点,总代价3·c·n²/16 = (3/16)c·n²
    • j层:总代价3ʲ·c·(n/4ʲ)² = (3/16)ʲ·c·n²
    • 叶节点(j=log₄ n):总代价Θ(n^(log₄ 3))log₄3≈0.79,可忽略)。
  • 总代价求和:求和为等比级数c·n²·Σⱼ₌₀^∞ (3/16)ʲ = c·n²·(1/(1-3/16)) = (16/13)c·n²,故T(n)=O(n²)
(2)递归式T(n)=T(n/3)+T(2n/3)+O(n)
  • 递归树构建
    • 根节点代价c·n,子节点为T(n/3)T(2n/3)
    • j层:所有节点规模之和为nn/3 + 2n/3 =nn/9 + 2n/9 + 2n/9 +4n/9 =n),总代价c·n
    • 树高:最长路径n→2n/3→(2/3)²n→…→1,高度log_(3/2)n
  • 总代价求和:总层数log_(3/2)n,每层代价c·n,故T(n)=O(nlg n)

4.5 主方法求解递归式主方法是求解形如T(n)=aT(n/b)+f(n) 递归式的高效工具(a≥1b>1f(n)渐近正),核心是比较f(n)n^(log_b a)的增长速度。

1. 主定理(三种情况)

log_b a为递归树中叶节点代价的增长阶,f(n)为分解 + 合并的代价,三种情况对应 “叶节点主导”“均匀分布”“分解合并主导”:

情况条件(ε>0为常数)结论示例
1f(n) = O(n^(log_b a - ε))f(n)增长慢于n^(log_b a)T(n) = Θ(n^(log_b a))T(n)=9T(n/3)+nlog₃9=2f(n)=n=O(n^(2-1)),解Θ(n²)
2f(n) = Θ(n^(log_b a))f(n)n^(log_b a)增长同阶)T(n) = Θ(n^(log_b a)·lg n)T(n)=T(2n/3)+1log_(3/2)1=0f(n)=1=Θ(n⁰),解Θ(lg n)
3f(n) = Ω(n^(log_b a + ε))f(n)增长快于n^(log_b a))且满足正则条件a·f(n/b) ≤ c·f(n)c<1为常数,对足够大n成立)T(n) = Θ(f(n))T(n)=3T(n/4)+nlg nlog₄3≈0.79f(n)=nlg n=Ω(n^(0.79+0.2)),正则条件3·(n/4 lg(n/4)) ≤ (3/4)nlg n,解Θ(nlg n)
2. 局限性

主方法无法处理以下情况:

  • f(n)在情况 1 和 2 之间(如T(n)=2T(n/2)+nlg nf(n)=nlg n慢于n^(log₂2)=n但非多项式级慢);
  • 情况 3 不满足正则条件(如T(n)=2T(n/2)+nlg na·f(n/b)=2·(n/2 lg(n/2))=n(lg n -1),无法找到c<1使n(lg n -1) ≤c·nlg n)。

4.6 主定理的证明:严谨性验证

主定理的证明分两部分,核心是通过递归树求和,结合级数分析验证三种情况。

练习题

4.1

4.1-1 当 A 的所有元素均为负数时,FIND-MAXIMUM-SUBARRAY 返回什么?

返回数组中绝对值最小的元素(即最大的单个元素),及其自身作为左右边界(如 A=[-5,-3,-2],返回 (3,3,-2))。

4.1-2 对最大子数组问题,编写暴力求解方法的伪代码,其运行时间应为 Θ(n²)

枚举所有可能的连续子数组(共 n (n+1)/2 个),计算每个子数组的和,记录最大和及其边界。

BRUTE-FORCE-MAX-SUBARRAY(A)
1 n = A.length
2 max-sum = -∞  // 初始化为负无穷,应对所有元素为负的情况
3 left = 1
4 right = 1
5 for i = 1 to n
6     current-sum = 0  // 记录以i为起点的子数组的和
7     for j = i to n
8         current-sum = current-sum + A[j]
9         if current-sum > max-sum
10            max-sum = current-sum
11            left = i
12            right = j
13 return (left, right, max-sum)

4.1-3 实现暴力算法和递归算法,确定性能交叉点 n₀,修改递归算法的基本情况

开放类的题,AI答案如下,仅供参考

  • 性能交叉点 n₀:取决于硬件和实现,通常在 10~50 之间(如在普通 PC 上,n₀≈30,当 n>30 时,递归算法平均时间小于暴力算法);

  • 修改基本情况后的变化:交叉点 n₀' 会减小(如 n₀'≈20),因避免了小 n 的递归调用开销,进一步优化了递归算法的小 n 性能。

4.1-4 允许空子数组(和为 0),修改现有算法

修改最大子数组问题的定义,允许结果为空子数组(和为 0)

思路:递归算法:在比较左、右、跨越子数组的最大和后,增加 “与 0 比较” 的步骤,若最大和为负,则返回空子数组(边界可设为 (0,0),和为 0);

暴力算法:同理,若最终max-sum < 0,则返回 (0,0,0)。

MODIFIED-FIND-MAXIMUM-SUBARRAY(A, low, high)
1 if low == high
2     if A[low] > 0
3         return (low, high, A[low])
4     else
5         return (0, 0, 0)  // 空子数组,和为0
6 else
7     mid = floor((low + high)/2)
8     (left-low, left-high, left-sum) = MODIFIED-FIND-MAXIMUM-SUBARRAY(A, low, mid)
9     (right-low, right-high, right-sum) = MODIFIED-FIND-MAXIMUM-SUBARRAY(A, mid+1, high)
10    (cross-low, cross-high, cross-sum) = FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high)
11    // 比较三个和与0,取最大者
12    max-sum = max(left-sum, right-sum, cross-sum, 0)
13    if max-sum == left-sum
14        return (left-low, left-high, left-sum)
15    elif max-sum == right-sum
16        return (right-low, right-high, right-sum)
17    elif max-sum == cross-sum
18        return (cross-low, cross-high, cross-sum)
19    else
20        return (0, 0, 0)  // 返回空子数组

4.1-5 设计非递归、线性时间的最大子数组算法

使用如下思想设计非递归、线性时间(Θ(n))的最大子数组算法:从左至右处理数组,记录到目前为止的最大子数组;若已知 A [1..j] 的最大子数组,A [1..j+1] 的最大子数组要么是 A [1..j] 的最大子数组,要么是某个子数组 A [i..j+1](1≤i≤j+1)。

算法思想(Kadane 算法):维护两个变量:current-max(以当前元素 A [j] 为终点的最大子数组和)、global-max(全局最大子数组和);

遍历数组时,对每个 A [j],current-max = max(A[j], current-max + A[j])(选择 “从 A [j] 重新开始” 或 “延续之前的子数组”);

同时更新global-max = max(global-max, current-max),记录对应的边界。

仅遍历数组一次,时间为 Θ(n),

KADANE-MAX-SUBARRAY(A)
1 n = A.length
2 if n == 0
3     return (0, 0, 0)  // 空子数组
4 current-max = A[1]
5 global-max = A[1]
6 current-left = 1
7 global-left = 1
8 global-right = 1
9 for j = 2 to n
10    if A[j] > current-max + A[j]
11        current-max = A[j]
12        current-left = j
13    else
14        current-max = current-max + A[j]
15    // 更新全局最大
16    if current-max > global-max
17        global-max = current-max
18        global-left = current-left
19        global-right = j
20 // 允许空子数组时,若global-max < 0,返回(0,0,0)
21 if global-max < 0
22    return (0, 0, 0)
23 else
24    return (global-left, global-right, global-max)

4.2

4.2-1 用 Strassen 算法计算矩阵乘法

用 Strassen 算法计算如下矩阵乘法:[17​35​]×[64​82​]给出计算过程。

  1. 分解矩阵设 A = [[A₁₁,A₁₂],[A₂₁,A₂₂]] = [[1,3],[7,5]],B = [[B₁₁,B₁₂],[B₂₁,B₂₂]] = [[6,8],[4,2]],需计算 C = A×B = [[C₁₁,C₁₂],[C₂₁,C₂₂]]。

  2. 创建中间矩阵 S₁~S₁₀

    • S₁ = B₁₂ - B₂₂ = [8-2, ...]
    • S₂ = A₁₁ + A₁₂ = 1+3 = 4;
    • S₃ = A₂₁ + A₂₂ = 7+5 = 12;
    • S₄ = B₂₁ - B₁₁ = 4-6 = -2;
    • S₅ = A₁₁ + A₂₂ = 1+5 = 6;
    • S₆ = B₁₁ + B₂₂ = 6+2 = 8;
    • S₇ = A₁₂ - A₂₂ = 3-5 = -2;
    • S₈ = B₂₁ + B₂₂ = 4+2 = 6;
    • S₉ = A₁₁ - A₂₁ = 1-7 = -6;
    • S₁₀ = B₁₁ + B₁₂ = 6+8 = 14。
  3. 计算 7 个矩阵积 P₁~P₇

    • P₁ = A₁₁×S₁ = 1×6 = 6;
    • P₂ = S₂×B₂₂ = 4×2 = 8;
    • P₃ = S₃×B₁₁ = 12×6 = 72;
    • P₄ = A₂₂×S₄ = 5×(-2) = -10;
    • P₅ = S₅×S₆ = 6×8 = 48;
    • P₆ = S₇×S₈ = (-2)×6 = -12;
    • P₇ = S₉×S₁₀ = (-6)×14 = -84。
  4. 合并得到 C 的子矩阵

    • C₁₁ = P₅ + P₄ - P₂ + P₆ = 48 + (-10) - 8 + (-12) = 18;
    • C₁₂ = P₁ + P₂ = 6 + 8 = 14;
    • C₂₁ = P₃ + P₄ = 72 + (-10) = 62;
    • C₂₂ = P₅ + P₁ - P₃ - P₇ = 48 + 6 - 72 - (-84) = 66。

矩阵乘法结果为:[1862​1466​]​

4.2-2 为 Strassen 算法编写伪代码

  1. 基本情况:n=1 时,直接返回标量乘法结果;
  2. 分解:将矩阵分为 4 个 n/2×n/2 子矩阵(假设 n 为 2 的幂);
  3. 创建中间矩阵 S₁~S₁₀;
  4. 递归计算 P₁~P₇;
  5. 合并得到 C 的子矩阵。
  6. 辅助函数:需实现MATRIX-ADD(A,B)(矩阵加法)和MATRIX-SUB(A,B)(矩阵减法),时间均为 Θ(n²)。
// 矩阵加法:返回A+B,A和B均为n×n矩阵
MATRIX-ADD(A, B)
1 n = A.rows
2 let C be a new n×n matrix
3 for i = 1 to n
4     for j = 1 to n
5         C[i][j] = A[i][j] + B[i][j]
6 return C

// 矩阵减法:返回A-B,A和B均为n×n矩阵
MATRIX-SUB(A, B)
1 n = A.rows
2 let C be a new n×n matrix
3 for i = 1 to n
4     for j = 1 to n
5         C[i][j] = A[i][j] - B[i][j]
6 return C

// Strassen算法:返回A×B,n为2的幂
STRASSEN-MATRIX-MULTIPLY(A, B)
1 n = A.rows
2 if n == 1
3     let C be a new 1×1 matrix
4     C[1][1] = A[1][1] * B[1][1]
5     return C
6 // 分解A、B为4个n/2×n/2子矩阵
7 let A11, A12, A21, A22 be new (n/2)×(n/2) matrices
8 let B11, B12, B21, B22 be new (n/2)×(n/2) matrices
9 for i = 1 to n/2
10    for j = 1 to n/2
11        A11[i][j] = A[i][j]
12        A12[i][j] = A[i][j + n/2]
13        A21[i][j] = A[i + n/2][j]
14        A22[i][j] = A[i + n/2][j + n/2]
15        B11[i][j] = B[i][j]
16        B12[i][j] = B[i][j + n/2]
17        B21[i][j] = B[i + n/2][j]
18        B22[i][j] = B[i + n/2][j + n/2]
19 // 创建中间矩阵S1~S10
20 S1 = MATRIX-SUB(B12, B22)
21 S2 = MATRIX-ADD(A11, A12)
22 S3 = MATRIX-ADD(A21, A22)
23 S4 = MATRIX-SUB(B21, B11)
24 S5 = MATRIX-ADD(A11, A22)
25 S6 = MATRIX-ADD(B11, B22)
26 S7 = MATRIX-SUB(A12, A22)
27 S8 = MATRIX-ADD(B21, B22)
28 S9 = MATRIX-SUB(A11, A21)
29 S10 = MATRIX-ADD(B11, B12)
30 // 递归计算P1~P7
31 P1 = STRASSEN-MATRIX-MULTIPLY(A11, S1)
32 P2 = STRASSEN-MATRIX-MULTIPLY(S2, B22)
33 P3 = STRASSEN-MATRIX-MULTIPLY(S3, B11)
34 P4 = STRASSEN-MATRIX-MULTIPLY(A22, S4)
35 P5 = STRASSEN-MATRIX-MULTIPLY(S5, S6)
36 P6 = STRASSEN-MATRIX-MULTIPLY(S7, S8)
37 P7 = STRASSEN-MATRIX-MULTIPLY(S9, S10)
38 // 合并得到C的子矩阵
39 C11 = MATRIX-ADD(MATRIX-SUB(MATRIX-ADD(P5, P4), P2), P6)
40 C12 = MATRIX-ADD(P1, P2)
41 C21 = MATRIX-ADD(P3, P4)
42 C22 = MATRIX-SUB(MATRIX-SUB(MATRIX-ADD(P5, P1), P3), P7)
43 // 组合C11、C12、C21、C22为n×n矩阵C
44 let C be a new n×n matrix
45 for i = 1 to n/2
46    for j = 1 to n/2
47        C[i][j] = C11[i][j]
48        C[i][j + n/2] = C12[i][j]
49        C[i + n/2][j] = C21[i][j]
50        C[i + n/2][j + n/2] = C22[i][j]
51 return C

4.2-3 修改 Strassen 算法适应 n 非 2 的幂,证明时间为 Θ(n^lg7)

如何修改 Strassen 算法,使之适应矩阵规模 n 不是 2 的幂的情况,证明修改后的算法运行时间仍为 Θ(n^lg7)。

  • 修改方法
    1. 找最小的 2 的幂 m≥n,构造 m×m 矩阵 A' 和 B'(A'、B' 的前 n 行 n 列分别为 A、B,其余元素为 0);
    2. 用 Strassen 算法计算 C'=A'×B';
    3. 截取 C' 的前 n 行 n 列,得到 A×B 的结果。
  • 时间复杂度证明:补全和截取时间均为 Θ(n²),Strassen 计算 C' 的时间为 Θ(m^lg7)=Θ(n^lg7)(m≤2n),总时间为 Θ(n^lg7)+Θ(n²)=Θ(n^lg7),故修改后算法运行时间仍为Θ(n^lg7)

4.2-4 3×3 矩阵乘法的 k 次乘法与 n×n 矩阵乘法时间

如果可以用 k 次乘法操作(假定乘法交换律不成立)完成两个 3×3 矩阵相乘,那么能在 o (n^lg7) 时间内完成 n×n 矩阵相乘的最大 k 是多少?此时算法的运行时间是怎样的?

  1. 分治
    • 将 n×n 矩阵分为 9 个 n/3×n/3 子矩阵(类比 2×2 分治),递归计算 9 个 n/3×n/3 矩阵乘法,若每个 3×3 乘法需 k 次标量乘法,则递归式为 T (n) = k・T (n/3) + Θ(n²)(Θ(n²) 为加减代价)。
  2. 时间复杂度分析
    • 目标:使 T (n) = o (n^lg7),即 limₙ→∞ T (n)/n^lg7 =0;
    • 用主定理分析递归式 T (n)=kT (n/3)+Θ(n²):
      • 主定理中,a=k,b=3,log_b a=log₃k;
      • 若 log₃k <lg7(即 k < 3^lg7),则 T (n)=Θ(n^log₃k);
      • 计算 3^lg7:因 3^lg7 =7^lg3≈7^1.585≈19.8,故最大整数 k=19(k=19<19.8,k=20>19.8)。
  3. 运行时间:当 k=19 时,log₃19≈2.68<lg7≈2.81,故 T (n)=Θ(n^log₃19)=o (n^lg7)。
  • 最大 k 值:19;
  • 算法运行时间:Θ(n^log₃19)(因 log₃19≈2.68<lg7≈2.81,故 Θ(n^log₃19)=o (n^lg7))。

4.2-5 Pan 的矩阵乘法方法的渐近性能

V.Pan 发现三种矩阵乘法方法:132464 次乘法完成 68×68 矩阵相乘,143640 次乘法完成 70×70 矩阵相乘,155424 次乘法完成 72×72 矩阵相乘。当用于分治矩阵乘法时,哪种方法的渐近运行时间最佳?与 Strassen 算法相比性能如何?

求解过程
  1. 分治递归式
    • 设用 s×s 矩阵乘法需 m 次标量乘法,分治时将 n×n 矩阵分为 (s×s) 个子矩阵,递归式为 T (n) = m・T (n/s) + Θ(n²);
    • 由主定理,T (n)=Θ(n^log_s m)(当 log_s m >2 时,即 m>s²)。
  2. 计算三种方法的 log_s m
    • 68×68 方法:s=68,m=132464,log_68 132464 = ln132464/ln68 ≈11.79/4.22≈2.794;
    • 70×70 方法:s=70,m=143640,log_70 143640≈ln143640/ln70≈11.88/4.24≈2.802;
    • 72×72 方法:s=72,m=155424,log_72 155424≈ln155424/ln72≈11.95/4.28≈2.792;
  3. 比较 Strassen 算法
    • Strassen 算法的 log_2 7≈2.807;
    • 三种方法的 log_s m 均小于 2.807,故渐近性能均优于 Strassen 算法,其中 72×72 方法的 log_s m 最小(2.792),渐近性能最佳。
  • 最佳渐近性能方法:72×72 矩阵乘法方法(log_72 155424≈2.792 最小);
  • 与 Strassen 算法比较:三种方法的 log_s m(≈2.792~2.802)均小于 Strassen 算法的 log_2 7≈2.807,故三种方法的渐近性能均优于 Strassen 算法,72×72 方法最优。

4.2-6 k×n 矩阵与 n×k 矩阵相乘的 Strassen 子进程时间

用 Strassen 算法作为子进程,计算 k×n 矩阵 A 和 n×k 矩阵 B 的乘积,最快需要多长时间?对 A 为 n×k 矩阵、B 为 k×n 矩阵的情况,回答相同的问题。

  1. A (k×n) × B (n×k)
    • 结果 C 为 k×k 矩阵,C [i][j] = Σₜ₌₁ⁿ A [i][t]・B [t][j];
    • 方法:将 A 视为 k 个 1×n 行向量,B 视为 k 个 n×1 列向量,C [i][j] 为第 i 行向量与第 j 列向量的点积;但更高效的分治方法是 “补全为方阵”:
      • 找 m=2ᵏ≥max (k,n),构造 m×m 矩阵 A'(前 k 行 n 列为 A,其余为 0)和 B'(前 n 行 k 列为 B,其余为 0);
      • 用 Strassen 算法计算 C'=A'×B',截取前 k 行 k 列为 C;
    • 时间:T (m)=Θ(m^lg7),因 m≤2max (k,n),故时间为 Θ((max (k,n))^lg7)。
  2. A (n×k) × B (k×n)
    • 结果 C 为 n×n 矩阵,同理补全为 m×m 方阵(m≥max (n,k)),用 Strassen 算法计算,时间仍为 Θ((max (n,k))^lg7)。
  • k×n 矩阵 × n×k 矩阵:最快时间为Θ((max(k,n))^lg7)
  • n×k 矩阵 × k×n 矩阵:最快时间同样为Θ((max(n,k))^lg7)

4.2-7 三次实数乘法完成复数相乘

设计算法,仅使用三次实数乘法即可完成复数 a+bi 和 c+di 相乘,算法需接收 a、b、c、d 为输入,生成实部 ac-bd 和虚部 ad+bc。

  1. 常规复数乘法:需四次实数乘法(ac、bd、ad、bc),目标用三次乘法实现。
  2. 算法设计(Gauss 复数乘法)
    • 计算 M1 = (a+b)(c+d) = ac + ad + bc + bd(1 次乘法);
    • 计算 M2 = a・c(2 次乘法);
    • 计算 M3 = b・d(3 次乘法);
    • 实部 = M2 - M3 = ac - bd(无乘法);
    • 虚部 = M1 - M2 - M3 = (ac+ad+bc+bd) - ac - bd = ad + bc(无乘法)。
COMPLEX-MULTIPLY(a, b, c, d)
1 M1 = (a + b) * (c + d)  // 第一次乘法
2 M2 = a * c              // 第二次乘法
3 M3 = b * d              // 第三次乘法
4 real-part = M2 - M3      // 实部:ac - bd
5 imag-part = M1 - M2 - M3 // 虚部:ad + bc
6 return (real-part, imag-part)

4.3

4.3-1 证明 T (n)=T (n-1)+n 的解为 O (n²)

  1. 猜测解的形式:T (n) ≤ c・n²(c 为常数);
  2. 归纳假设:假设对所有 m <n,T (m) ≤ c・m²;
  3. 代入递归式:T(n)=T(n−1)+n≤c⋅(n−1)2+n=c⋅(n2−2n+1)+n=c⋅n2−2c⋅n+c+n
  4. 化简:需证明 c・n² - 2c・n + c + n ≤ c・n²,即 -2c・n + c + n ≤0 → n (1-2c) + c ≤0;
  5. 选择 c≥1:当 c=1 时,n (1-2) +1 = -n +1 ≤0(n≥1),故 T (n) ≤1・n²,得证。

4.3-2 证明 T (n)=T (⌈n/2⌉)+1 的解为 O (lg n)

  1. 猜测 T (n) ≤ c・lg n + d(c≥1,d≥1);
  2. 归纳假设 T (⌈n/2⌉) ≤ c・lg (⌈n/2⌉) + d;
  3. 代入得 T (n) ≤c・lg ((n+1)/2)+d+1 ≤c・(1+lg n)-c+d+1 =c・lg n +d+1 ≤c・lg n +2d;
  4. 基本情况 n=1 时,T (1)=1 ≤2d(d≥1/2);故 T (n)=O (lg n)。

4.3-3 证明 T (n)=2T (⌊n/2⌋)+n 的解为 Ω(nlg n)

证明递归式 T (n)=2T (⌊n/2⌋)+n 的解为 Ω(nlg n)(已知其解为 O (nlg n),故解为 Θ(nlg n))。

  1. 猜测 T (n) ≥ c・nlg n(c=1/4);
  2. 归纳假设 T (⌊n/2⌋) ≥c・⌊n/2⌋・lg (⌊n/2⌋);
  3. 代入得 T (n) ≥2c・(n/4)(lg n-2)+n = (c/2) nlg n +n (1-2c),当 c=1/4 时,T (n)≥(1/8) nlg n + (1/2) n ≥(1/8) nlg n;故 T (n)=Ω(nlg n),结合已知的 O (nlg n),得 T (n)=Θ(nlg n)。

4.3-4 调整归纳假设处理 T (1)=1 的边界条件

证明:通过做出不同的归纳假设,不必调整边界条件即可克服递归式 T (n)=2T (⌊n/2⌋)+n 中边界条件 T (1)=1 带来的困难。

  1. 基本情况 n=1:T (1)=1 ≤c・0 +d =d(d≥1),成立;
  2. 归纳步骤:T (n) ≤2 [c・⌊n/2⌋・lg (⌊n/2⌋)+d]+n ≤2 [c・(n/2)(lg n-1)+d]+n =c・nlg n -c・n +2d +n;
  3. 取 c=1,得 T (n) ≤nlg n +2d(d≥1),仍为 O (nlg n);

4.3-5 证明归并排序严格递归式 T (n)=T (⌈n/2⌉)+T (⌊n/2⌋)+Θ(n) 的解为 Θ(nlg n)

题目

证明归并排序的 “严格” 递归式 T (n)=T (⌈n/2⌉)+T (⌊n/2⌋)+Θ(n) 的解为 Θ(nlg n)。

求解过程
  1. 证明上界 O (nlg n)

    • 猜测 T (n) ≤c・nlg n +d(c,d 为常数);
    • 归纳假设:T (⌈n/2⌉) ≤c・⌈n/2⌉・lg (⌈n/2⌉)+d,T (⌊n/2⌋) ≤c・⌊n/2⌋・lg (⌊n/2⌋)+d;
    • 代入递归式:(取)
    • 化简⌈n/2⌉+⌊n/2⌋=n,且⌈n/2⌉lg (⌈n/2⌉)+⌊n/2⌋lg (⌊n/2⌋) ≤nlg (n/2)+1(因最大情况为 n 偶数时,n/2・lg (n/2)+n/2・lg (n/2)=nlg (n/2));
    • 故 T (n) ≤c [nlg (n/2)+1] +2d +cn =c (nlg n -n +1) +2d +cn =c・nlg n +c +2d,取 c≥1,d≥1,得 T (n)=O (nlg n)。
  2. 证明下界 Ω(nlg n)

    • 猜测 T (n) ≥c・nlg n;
    • 归纳假设:T (⌈n/2⌉) ≥c・⌈n/2⌉・lg (⌈n/2⌉),T (⌊n/2⌋) ≥c・⌊n/2⌋・lg (⌊n/2⌋);
    • 代入递归式:(取)
    • 化简:⌈n/2⌉lg (⌈n/2⌉)+⌊n/2⌋lg (⌊n/2⌋) ≥nlg (n/2)(n 偶数时等号成立);
    • 故 T (n) ≥c・nlg (n/2) +cn/2 =c (nlg n -n) +cn/2 =c・nlg n -cn/2,取 c≤1,得 T (n)≥(1/2) nlg n(n≥2),即 T (n)=Ω(nlg n)。

          则:上界 O (nlg n) 和下界 Ω(nlg n),故 T (n)=Θ(nlg n)。

4.3-6 证明 T (n)=2T (⌊n/2⌋+17)+n 的解为 O (nlg n)

  1. 猜测 T (n) ≤c・nlg n +d(c≥1,d 足够大);
  2. 归纳假设 T (⌊n/2⌋+17) ≤c・(⌊n/2⌋+17)・lg (⌊n/2⌋+17) +d;
  3. 代入得 T (n) ≤2c・(n/2+17)(1+lg n) +2d +n ≤c・n (1+lg n) +34c (1+lg n) +2d +n;
  4. 当 n 足够大时,n (c+1) +34c・lg n ≤c・nlg n,故 T (n) ≤2c・nlg n,即 O (nlg n);故 T (n)=O (nlg n)。

4.3-7 用代入法证明 T (n)=4T (n/3)+n 的解为 Θ(n^log₃4)

假设 T (n)≤c・n^log₃4 -d・n(d=3);

代入得 T (n)≤4 [c・(n/3)^log₃4 -d・n/3]+n =c・n^log₃4 -n (4d/3 -1) ≤c・n^log₃4(d=3 时,4d/3-1=3≥0);

基本情况 n=1 时,取 c≥T (1)+3;结合下界 Ω(n^log₃4),得 T (n)=Θ(n^log₃4)。

4.3-8 用代入法证明 T (n)=4T (n/2)+n 的解为 Θ(n²)

  1. 假设 T (n)≤c・n² -d・n(d=1);

  2. 代入得 T (n)≤4 [c・(n/2)² -d・n/2]+n =c・n² -n (2d-1) ≤c・n²(d=1 时,2d-1=1≥0);

  3. 基本情况 n=1 时,取 c≥T (1)+1;结合下界 Ω(n²),得 T (n)=Θ(n²)。

4.3-9 用改变变量法求解 T (n)=3T (√n)+log n

  1. 令 n=2ᵐ,S (m)=T (2ᵐ),递归式变为 S (m)=3S (m/2)+m;
  2. 主方法得 S (m)=Θ(m^log₂3);
  3. 回代 m=log n,得 T (n)=Θ((log n)^log₂3);故递归式的渐近紧确解为Θ((log n)^log₂3)(或等价表示为 Θ((ln n)^ln3/ln2))。

4.4

4.4-1 用递归树求 T (n)=3T (⌊n/2⌋)+n 的渐近上界,代入法验证

  1. 递归树构建

    • 根节点(j=0):代价 n,3 个子节点(a=3),规模 n/2;
    • 第 j 层:节点数 3ʲ,每个节点代价 n/2ʲ,总代价 3ʲ・n/2ʲ =n・(3/2)ʲ;
    • 叶节点(j=log₂n):节点数 3^(log₂n)=n^log₂3,每个代价 Θ(1),总代价 Θ(n^log₂3);
    • 总代价:T (n) =Σⱼ₌₀^(log₂n-1) n・(3/2)ʲ + Θ(n^log₂3)。
  2. 求和计算

    • 求和项为等比级数,首项 a=n,公比 r=3/2,项数 k=log₂n:Σj=0(​k−1)n⋅(3/2)j=n⋅[(3/2)k−1]/[(3/2)−1]=2n⋅[(3/2)log2​n−1]=2n⋅(nlog2​(3/2)−1)=2n(1+log2​(3/2))−2n=2nlog2​3−2n
    • 总代价:T (n) =2n^log₂3 -2n + Θ(n^log₂3) =Θ(n^log₂3)(因 log₂3≈1.58>1,n^log₂3 主导 n)。
  3. 代入法验证

    • 假设 T (n) ≤c・n^log₂3;
    • 代入得 T (n)=3T (⌊n/2⌋)+n ≤3c・(n/2)^log₂3 +n =3c・n^log₂3 /2^log₂3 +n =3c・n^log₂3 /3 +n =c・n^log₂3 +n;
    • 修改假设为 T (n) ≤c・n^log₂3 -d・n,代入得 T (n) ≤c・n^log₂3 -d・n +n ≤c・n^log₂3(d≥1),得证。

4.4-2 用递归树求 T (n)=T (n/2)+n² 的渐近上界,代入法验证

  1. 递归树构建

    • 根节点(j=0):代价 n²,1 个子节点(a=1),规模 n/2;
    • 第 j 层:节点数 1ʲ=1,每个节点代价 (n/2ʲ)²,总代价 n²/4ʲ;
    • 叶节点(j=log₂n):节点数 1,代价 Θ(1);
    • 总代价:T (n) =Σⱼ₌₀^(log₂n-1) n²/4ʲ + Θ(1)。
  2. 求和计算

    • 求和项为等比级数,首项 a=n²,公比 r=1/4,项数 k=log₂n:Σj=0(​k−1)n2/4j≤Σj=0∞​n2/4j=n2⋅1/(1−1/4)=(4/3)n2
    • 总代价:T (n) ≤(4/3) n² + Θ(1) =O (n²)。
  3. 代入法验证

    • 假设 T (n) ≤c・n²;
    • 代入得 T (n)=T (n/2)+n² ≤c・(n/2)² +n² =c・n²/4 +n² =n²(c/4 +1);
    • 选择 c≥4/3:c/4 +1 ≤c →1 ≤3c/4 →c≥4/3,故 T (n) ≤(4/3) n²,得证。

4.4-3 用递归树求 T (n)=4T (n/2+2)+n 的渐近上界,代入法验证

  1. 递归树构建

    • 根节点(j=0):代价 n,4 个子节点(a=4),规模 n/2+2;
    • 第 j 层:节点数 4ʲ,每个节点代价≈n/2ʲ(忽略 + 2,因 n 足够大时,n/2ʲ主导 2),总代价≈4ʲ・n/2ʲ =n・2ʲ;
    • 叶节点(j=log₂n):节点数 4^(log₂n)=n²,每个代价 Θ(1),总代价 Θ(n²);
    • 总代价:T (n) ≈Σⱼ₌₀^(log₂n-1) n・2ʲ + Θ(n²)。
  2. 求和计算

    • 求和项为等比级数,首项 a=n,公比 r=2,项数 k=log₂n:Σj=0(​k−1)n⋅2j=n⋅(2k−1)/(2−1)=n⋅(n−1)=n2−n
    • 总代价:T (n) ≈n² -n + Θ(n²) =O (n²)。
  3. 代入法验证

    • 假设 T (n) ≤c・n² -d・n(c≥1,d≥1);
    • 代入得 T (n)=4T (n/2+2)+n ≤4 [c・(n/2+2)² -d・(n/2+2)] +n =4 [c・(n²/4 +2n +4) -d・n/2 -2d] +n =c・n² +8c・n +16c -2d・n -8d +n;
    • 化简:T (n) ≤c・n² +n (8c +1 -2d) +16c -8d;
    • 选择 c=1,d=5:8c+1-2d=8+1-10=-1≤0,16c-8d=16-40=-24≤0,故 T (n) ≤n²,得证。

4.4-4 用递归树求 T (n)=T (n-1)+1 的渐近上界,代入法验证

  1. 递归树构建

    • 根节点(j=0):代价 1,1 个子节点(a=1),规模 n-1;
    • 第 j 层:节点数 1,代价 1,总代价 1;
    • 叶节点(j=n-1):规模 1,代价 Θ(1);
    • 总代价:T (n) =Σⱼ₌₀^(n-2) 1 + Θ(1) =n-1 + Θ(1) =O (n)。
  2. 代入法验证

    • 假设 T (n) ≤c・n;
    • 代入得 T (n)=T (n-1)+1 ≤c・(n-1) +1 =c・n -c +1;
    • 选择 c≥1:-c +1 ≤0 →c≥1,故 T (n) ≤c・n,得证。

4.4-5 用递归树求 T (n)=T (n-1)+T (n/2)+n 的渐近上界,代入法验证

  1. 递归树构建

    • 根节点(j=0):代价 n,两个子节点 T (n-1) 和 T (n/2);
    • T (n-1) 分支:每层代价≈n-j(j 为层数),直到规模 1,共 n 层,总代价≈Σⱼ₀^(n-1) (n-j) =n (n+1)/2=O (n²);
    • T (n/2) 分支:每层代价≈n/2ʲ,共 log₂n 层,总代价≈Σⱼ₀^(log₂n-1) n/2ʲ=2n=O (n);
    • 总代价:T (n) ≈O (n²) +O (n) =O (n²)。
  2. 代入法验证

    • 假设 T (n) ≤c・n²;
    • 代入得 T (n)=T (n-1)+T (n/2)+n ≤c・(n-1)² +c・(n/2)² +n =c・(n²-2n+1) +c・n²/4 +n = (5c/4)・n² +n (1-2c) +c;
    • 选择 c≥4:5c/4 ≤c →c≥0(恒成立),1-2c ≤1-8=-7≤0,故 T (n) ≤(5c/4)・n² ≤2c・n²(c≥4),得证。

4.4-6 用递归树论证 T (n)=T (n/3)+T (2n/3)+cn 的解为 Ω(nlg n)

对递归式 T (n)=T (n/3)+T (2n/3)+cn(c 为常数),利用递归树论证其解为 Ω(nlg n)。

求解过程
  1. 递归树核心观察:递归树中,每层所有节点的规模之和恒为 n。不管是根节点(规模 n),还是拆分后的子节点(n/3 + 2n/3 = n),甚至更深层的节点,所有节点的规模加起来始终等于初始规模 n。由于每层的总代价 = c × 该层所有节点的规模之和,因此每层总代价恒为 cn(比如根节点代价 cn,第 1 层代价 c×(n/3) + c×(2n/3) = cn,第 2 层代价 c×(n/9) + c×(2n/9) + c×(2n/9) + c×(4n/9) = cn,以此类推)。

  2. 递归树的最小高度(关键下界):递归会一直拆分,直到节点规模≤1 时终止。要找总代价的下界,需确定递归树的最小高度 h_min—— 即从根节点到叶节点的最短路径长度(路径越短,层数越少,但即使是最少层数,也要保证总代价足够大)。最短路径对应规模衰减最快的分支:每次选择拆分后规模更小的子问题(n→n/3→n/3²→…→1)。令 n/3^h_min ≤ 1,两边取对数得 h_min ≥ log₃n(因为 3^h_min ≥ n)。

  3. 总代价下界计算:递归树至少有 h_min ≥ log₃n 层,且每层总代价为 cn,因此总代价的下界为:T (n) ≥ 层数 × 每层代价 ≥ log₃n × cn = c×n×log₃n。根据对数换底公式,log₃n = lg n /lg 3(lg 表示以 2 为底的对数),因此 T (n) ≥ c×n×(lg n /lg 3)。令常数 k = c /lg 3(k>0,因为 c>0、lg3>0),则 T (n) ≥ k×nlg n,满足 Ω(nlg n) 的定义(存在常数 k>0 和 n₀,当 n≥n₀时,T (n)≥k×nlg n)。

4.4-7 用递归树求 T (n)=4T (⌊n/2⌋)+cn 的渐近紧确界,代入法验证

  1. 验证(上界 O (n²) 和下界 Ω(n²))

    • 上界证明:假设 T (n) ≤ d×n²(d 为常数),代入递归式:T(n) = 4T(⌊n/2⌋) + cn ≤ 4×d×(n/2)² + cn = 4×d×n²/4 + cn = d n² + cn。直接假设无法消去 cn,调整假设为 T (n) ≤ d n² - e n(e 为常数):T(n) ≤ 4×[d×(n/2)² - e×(n/2)] + cn = d n² - 2e n + cn = d n² - n(2e - c)。取 e ≥ c/2,則 2e - c ≥ 0,因此 T (n) ≤ d n²,上界 O (n²) 得证。

    • 下界证明:假设 T (n) ≥ d×n²(d 为常数),代入递归式:T(n) = 4T(⌊n/2⌋) + cn ≥ 4×d×(n/4)² + cn = d×n²/4 + cn。当 n 足够大时(如 n ≥ 4c/(3d)),cn ≤ 3d n²/4,因此:T (n) ≥ d n²/4 + 3d n²/4 = d n²,下界 Ω(n²) 得证。

4.4-8 用递归树求 T (n)=T (n-a)+T (a)+cn 的渐近紧确解

  1. 递归树结构分析:递归式每次将规模 n 拆分为 “n-a” 和 “a”:

    • 主分支:T (n)→T (n-a)→T (n-2a)→…→T (a),共 (n-a)/a ≈ n/a 层(从 n 减到 a,每次减 a)。每层的代价为 cn(因为拆分出的 T (a) 是常数,不随 n 变化,主分支的 cn 是主要代价)。
    • 常数分支:每个 T (a) 的代价为 Θ(1)(a 是固定常数,规模 a 的子问题代价固定),总共有 n/a 个 T (a),因此常数分支的总代价为 O (n/a) = O (n)(远小于 n²,可忽略)。
  2. 总代价计算:主分支的总代价≈层数 × 每层代价 ≈ (n/a)×cn = (c/a) n²,常数分支代价可忽略,因此总代价为 Θ(n²),即渐近紧确解为 Θ(n²)。

4.4-9 用递归树求 T (n)=T (αn)+T ((1-α) n)+cn 的渐近紧确解

  1. 递归树核心性质:无论 α 取 (0,1) 内的任何值,拆分后两个子节点的规模之和始终为 αn + (1-α) n = n。因此,每层所有节点的规模之和恒为 n,每层总代价 = c× 规模之和 = cn(与 4.4-6 同理,比如 α=1/3 时,第 1 层代价 c×(n/3) + c×(2n/3) = cn;α=1/4 时,第 1 层代价 c×(n/4) + c×(3n/4) = cn,以此类推)。

  2. 递归树的高度:递归终止于节点规模≤1,树的高度取决于规模衰减最慢的分支(最长路径)。假设 α<1-α(即 α<0.5),最长路径为 n→(1-α) n→(1-α)²n→…→1。令 (1-α)^h ≤1,两边取对数得 h ≥ log_{1/(1-α)} n(因为 (1-α)^h ≤1 ⇒ h ≥ log_{1/(1-α)} n)。

  3. 总代价计算:层数 h≥log_{1/(1-α)} n,且每层总代价为 cn,因此总代价≈h×cn = Θ(n log n)(因为 log_{1/(1-α)} n 与 lg n 是常数倍关系,比如 log_{1/(1-α)} n = lg n /lg [1/(1-α)],常数因子可忽略)。

4.5

4.5-1 用主方法求下列递归式的渐近紧确界

主方法适用于 T (n)=aT (n/b)+f (n),先计算 log_b a(a=2,b=4,故 log_4 2=0.5),再根据 f (n) 与 n^0.5 的关系判断情况。

a. T(n)=2T(n/4)+1

  • log_b a=0.5,f(n)=1;
  • f (n)=1 = O (n^{0.5-ε})(取 ε=0.5,n^{0.5-0.5}=n^0=1,满足 1=O (1)),属于主方法情况 1;
  • 结论:T (n)=Θ(n^0.5)=Θ(√n)。

b. T(n)=2T(n/4)+√n

  • log_b a=0.5,f(n)=√n =n^0.5;
  • f (n)=Θ(n^0.5)=Θ(n^log_b a),属于主方法情况 2;
  • 结论:T (n)=Θ(n^log_b a・lg n)=Θ(√n・lg n)。

c. T(n)=2T(n/4)+n

  • log_b a=0.5,f(n)=n =n^1;
  • f (n)=Ω(n^{0.5+ε})(取 ε=0.5,n^{0.5+0.5}=n^1,满足 n=Ω(n)),且验证正则条件:a f (n/b)=2×f (n/4)=2×(n/4)=n/2 ≤ c f (n)(取 c=1/2<1),属于主方法情况 3;
  • 结论:T (n)=Θ(f (n))=Θ(n)。

d. T(n)=2T(n/4)+n²

  • log_b a=0.5,f(n)=n²;
  • f (n)=Ω(n^{0.5+ε})(取 ε=1.5,n^{0.5+1.5}=n^2,满足 n²=Ω(n²)),且验证正则条件:a f (n/b)=2×f (n/4)=2×(n²/16)=n²/8 ≤ c f (n)(取 c=1/8<1),属于主方法情况 3;
  • 结论:T (n)=Θ(f (n))=Θ(n²)。

4.5-2 Caesar 教授的矩阵乘法算法

Caesar 教授设计分治矩阵乘法算法:将 n×n 矩阵分解为 n/4×n/4 子矩阵,分解和合并步骤共花费 Θ(n²) 时间,创建 a 个子问题,递归式为 T (n)=aT (n/4)+Θ(n²)。若要使算法渐近快于 Strassen 算法(T (n)=Θ(n^lg7)≈Θ(n².81)),a 的最大整数值是多少?

  1. 算法要渐近快于 Strassen 算法,需满足 T (n)=o (n^lg7)(即 T (n) 的增长速度比 n^lg7 慢)。对递归式 T (n)=aT (n/4)+Θ(n²),用主方法分析:

    • a 是子问题数,b=4,故 log_4 a 是子问题规模的增长阶;
    • f (n)=Θ(n²),需递归式的解由 n^log_4 a 主导(主方法情况 1),即 log_4 a < lg7(只有当 n^log_4 a 的增长阶低于 n^lg7 时,T (n)=o (n^lg7))。
  2. 将不等式 log_4 a < lg7 变形:a <4^lg7 = (2²)^lg7 = 2^(2lg7) = 7^(lg4)(因为 a^log_b c = c^log_b a)。计算 7^lg4≈7^1.585≈7×2.27≈15.89,因此 a 的最大整数值为 15(a 必须是整数,且 15<15.89,16>15.89)。

4.5-3 用主方法证明二分查找递归式的解为 Θ(lg n)

用主方法证明:二分查找递归式 T (n)=T (n/2)+Θ(1) 的解是 T (n)=Θ(lg n)。

  1. 二分查找递归式为 T (n)=1×T (n/2)+Θ(1),即 a=1,b=2,f (n)=Θ(1)。

  2. 计算 log_b a:log_2 1=0(因为 2^0=1)。

  3. f (n)=Θ(1)=Θ(n^0)=Θ(n^log_b a),满足主方法情况 2(f (n) 与 n^log_b a 同阶)。

  4. 主方法情况 2 的解为 T (n)=Θ(n^log_b a・lg n)=Θ(n^0・lg n)=Θ(lg n)。

4.5-4 主方法能否应用于 T (n)=4T (n/2)+n²lg n?给出渐近上界

  1. 主方法适用性判断:递归式 T (n)=4T (n/2)+n²lg n,a=4,b=2,log_2 4=2,f (n)=n²lg n。主方法的三种情况均不满足:

    • 情况 1:需 f (n)=O (n^{2-ε})(ε>0),但 n²lg n 的增长比 n^{2-ε} 快(lg n 是增长项),不满足;
    • 情况 2:需 f (n)=Θ(n²),但 n²lg n 比 n² 多了 lg n 项,不满足;
    • 情况 3:需 f (n)=Ω(n^{2+ε})(ε>0),但 n²lg n 的增长比 n^{2+ε} 慢(lg n 增长慢于 n^ε),不满足;因此主方法不能应用。
  2. 代入法求渐近上界:猜测 T (n) ≤ c・n²lg²n(c 为常数),代入递归式:T(n) = 4T(n/2) + n²lg n ≤ 4×c×(n/2)²×lg²(n/2) + n²lg n。化简:4×c×(n²/4)×(lg n - 1)² + n²lg n = c n²(lg²n - 2lg n + 1) + n²lg n。整理得:c n²lg²n - 2c n²lg n + c n² + n²lg n ≤ c n²lg²n。需满足 - 2c n²lg n + c n² + n²lg n ≤ 0,即 lg n (1-2c) + c ≤ 0。取 c≥1,当 n 足够大时(如 n≥2^c),lg n (1-2c) ≤ -lg n,且 - lg n + c ≤ 0,因此不等式成立,故 T (n) ≤ c・n²lg²n,即渐近上界为 O (n²lg²n)。

4.5-5 构造不满足正则条件的 f (n)

考虑主定理情况 3 的正则条件:对某个常数 c<1,a f (n/b) ≤c f (n)。给出一个例子,其中 a≥1,b>1,f (n) 满足情况 3 的其他条件(f (n)=Ω(n^{log_b a+ε})),但不满足正则条件。

  1. 构造思路:需设计 f (n),使得 a f (n/b) > c f (n) 对所有 c<1 成立(即正则条件不满足),同时满足 f (n)=Ω(n^{log_b a+ε})。取 a=2,b=2(log_2 2=1),设计 f (n)=n²・2^{sin (lg n)}。

  2. 验证条件

    • 满足情况 3 其他条件:log_b a=1,取 ε=1,f (n)=n²・2^{sin (lg n)}=Ω(n^{1+1})=Ω(n²),符合 f (n)=Ω(n^{log_b a+ε});
    • 不满足正则条件:a f(n/b)=2f(n/2)=2×(n/2)²×2^{sin(lg(n/2))}=2×(n²/4)×2^{sin(lg n - lg 2)}=n²/2×2^{sin(lg n)cos(lg 2) - cos(lg n)sin(lg 2)}。
      由于 sin (lg n) 的取值范围是 [-1,1],存在无穷多个 n 使 sin (lg n)=1
      此时:a f(n/b)=n²/2×2^{cos(lg 2)}≈n²/2×2^{0.766}≈0.85n²
      若取 c=0.4(c<1),则 c f (n)=0.4×n²×2^1=0.8n²,此时 0.85n²>0.8n²,即 a f (n/b) > c f (n),正则条件不成立。
  • f (n)=Ω(n²)=Ω(n^{log_2 2+1}),满足情况 3 其他条件;
  • 存在无穷多个 n 使 2f (n/2) > c f (n)(如 c=0.4),不满足正则条件,故 f (n) 符合要求。

4.6

4.6-1 当 b 为正整数时,给出 n_j 的准确表达式

对 b 是正整数而非任意实数的情况,给出公式 (4.27) 中 n_j 的简单而准确的表达式

  1. 递推关系展开:当 b 为正整数时,n_j=⌈n_{j-1}/b⌉,展开前几项:

    • n_1=⌈n/b⌉;
    • n_2=⌈n_1/b⌉=⌈⌈n/b⌉/b⌉;
    • 归纳可得:n_j=⌈n/b^j⌉(因为对整数 b 和任意实数 x,⌈⌈x⌉/b⌉=⌈x/b⌉,这是整数除法的性质)。
  2. 归纳法验证

    • 基础情况 j=1:n_1=⌈n/b⌉=⌈n/b^1⌉,成立;
    • 归纳假设:假设 n_{j-1}=⌈n/b^{j-1}⌉;
    • 归纳步骤:n_j=⌈n_{j-1}/b⌉=⌈⌈n/b^{j-1}⌉/b⌉=⌈n/b^j⌉,成立。

4.6-2 证明 T (n)=aT (n/b)+f (n) 的解(f (n)=Θ(n^log_b a lg^k n))

证明:如果 f (n)=Θ(n^log_b a lg^k n)(k≥0),那么主递归式的解为 T (n)=Θ(n^log_b a lg^{k+1} n)。为简单起见,假定 n 是 b 的幂。

  1. 递归式展开(n 是 b 的幂):令 n=b^m(m=log_b n),则递归式变为 T (b^m)=a T (b^{m-1}) + Θ(b^{m log_b a}・m^k)。由于 b^{m log_b a}=a^m(因为 b^{log_b a}=a,指数相乘得 b^{m log_b a}=a^m),因此递归式可改写为 T (b^m)=a T (b^{m-1}) + Θ(a^m・m^k)。

  2. 展开递归式求和:展开 T (b^m)(T (1)=Θ(1)):T (b^m) = a^m T (1) + Θ(求和(从 i=0 到 m-1)a^{m-i}・i^k)。其中 a^m T (1)=Θ(a^m)=Θ(n^log_b a)(低阶项,可忽略),主要代价来自求和部分:求和(从 i=0 到 m-1)a^{m-i}・i^k = a^m × 求和(从 i=0 到 m-1)i^k /a^i。当 a>1 时,求和(从 i=0 到 m-1)i^k /a^i ≤ 求和(从 i=0 到∞)i^k /a^i = C(C 为收敛常数),但更精确的近似需考虑 i^k 的影响:实际求和结果≈a^m・m^{k+1}/(a ln a)(通过积分近似,i^k 的积分与 m^{k+1} 成正比),因此 T (b^m)=Θ(a^m・m^{k+1})。

  3. 回代到 T (n):由于 m=log_b n,a^m=n^log_b a,m^{k+1}=lg^{k+1} n,因此 T (n)=Θ(n^log_b a lg^{k+1} n)。

当 n 是 b 的幂时,递归式展开后求和部分的主导项为 n^log_b a lg^{k+1} n,故 T (n)=Θ(n^log_b a lg^{k+1} n)。

4.6-3 证明正则条件蕴涵 f (n)=Ω(n^log_b a+ε)

证明:主定理中的情况 3 被过分强调了,从某种意义上来说,对某个常数 c<1,正则条件 a f (n/b) ≤c f (n) 成立本身就意味着存在常数 ε>0,使得 f (n)=Ω(n^log_b a+ε)。

  1. 正则条件递推:正则条件 a f (n/b) ≤c f (n),对 j 次递推得:a^j f(n/b^j) ≤c^j f(n) ⇒ f(n) ≥ (a/c)^j f(n/b^j)。

  2. 选择 j 使 n/b^j=1:令 j=log_b n(n 是 b 的幂),则 n/b^j=1,f (n/b^j)=f (1)=Θ(1)(常数),代入得:f(n) ≥ (a/c)^{log_b n} · Θ(1)。

  3. 化简并定义 ε:(a/c)^{log_b n}=n^{log_b (a/c)}(因为 x^{log_b y}=y^{log_b x}),而 log_b (a/c)=log_b a + log_b (1/c)。令 ε=log_b (1/c),由于 c<1,1/c>1,故 ε>0,因此:f(n) ≥ Θ(n^{log_b a + ε}) ⇒ f(n)=Ω(n^{log_b a + ε})。

二、思考题答案

4-1 递归式例子(渐近上界和下界)

题目

对下列每个递归式,给出 T (n) 的渐近上界和下界。假定 n≤2 时 T (n) 是常数。给出尽量紧确的界,并验证其正确性。a. T(n)=2T(n/2)+n⁴b. T(n)=T(7n/10)+nc. T(n)=16T(n/4)+n²d. T(n)=7T(n/3)+n²e. T(n)=7T(n/2)+n²f. T(n)=2T(n/4)+√ng. T(n)=T(n-2)+n²

求解过程

a. T(n)=2T(n/2)+n⁴

  • a=2,b=2,log_2 2=1,f(n)=n⁴=Ω(n^{1+ε})(ε=3);
  • 正则条件:2f (n/2)=2×(n⁴/16)=n⁴/8 ≤c f (n)(c=1/8<1),属于主方法情况 3;
  • 界:Θ(n⁴)。

b. T(n)=T(7n/10)+n

  • a=1,b=10/7,log_b 1=0,f(n)=n=Ω(n^{0+ε})(ε=1);
  • 正则条件:1×f (7n/10)=7n/10 ≤c n(c=7/10<1),属于主方法情况 3;
  • 界:Θ(n)。

c. T(n)=16T(n/4)+n²

  • a=16,b=4,log_4 16=2,f (n)=n²=Θ(n²),属于主方法情况 2;
  • 界:Θ(n² lg n)。

d. T(n)=7T(n/3)+n²

  • a=7,b=3,log_3 7≈1.77,f(n)=n²=Ω(n^{1.77+ε})(ε=0.23);
  • 正则条件:7f (n/3)=7×(n²/9)=7n²/9 ≤c n²(c=7/9<1),属于主方法情况 3;
  • 界:Θ(n²)。

e. T(n)=7T(n/2)+n²

  • a=7,b=2,log_2 7≈2.81,f (n)=n²=O (n^{2.81-ε})(ε=0.81),属于主方法情况 1;
  • 界:Θ(n^{lg7})≈Θ(n2.81)。

f. T(n)=2T(n/4)+√n

  • a=2,b=4,log_4 2=0.5,f (n)=√n=Θ(n0.5),属于主方法情况 2;
  • 界:Θ(√n lg n)。

g. T(n)=T(n-2)+n²

  • 求和:T (n)= 求和(从 k=1 到 n/2)(2k)²≈∫₀ⁿx²dx =n³/3,故界为 Θ(n³)。
答案

a. Θ(n⁴);b. Θ(n);c. Θ(n² lg n);d. Θ(n²);e. Θ(n^{lg7});f. Θ(√n lg n);g. Θ(n³)。

4-2 参数传递代价(二分查找与归并排序)

题目

分析三种参数传递策略(指针、复制数组、复制子数组)下,二分查找和归并排序的最坏情况运行时间递归式及解。

求解过程
  1. 二分查找(递归式基础:T (n)=T (n/2)+Θ(1))

    • 策略 1:指针传递(时间 =Θ(1)):递归式:T (n)=T (n/2)+Θ(1),主方法情况 2,解 =Θ(lg n)。
    • 策略 2:复制数组(时间 =Θ(N),N 为数组规模):递归式:T (n)=T (n/2)+Θ(n)(每次复制整个数组 n 个元素),主方法情况 3,解 =Θ(n)。
    • 策略 3:复制子数组(时间 =Θ(q-p+1),子数组规模):递归式:T (n)=T (n/2)+Θ(n)(每次复制子数组规模≈n/2,总复制时间≈n),解 =Θ(n)。
  2. 归并排序(递归式基础:T (n)=2T (n/2)+Θ(n))

    • 策略 1:指针传递(时间 =Θ(1)):递归式:T (n)=2T (n/2)+Θ(n),主方法情况 2,解 =Θ(n lg n)。
    • 策略 2:复制数组(时间 =Θ(N)):递归式:T (n)=2T (n/2)+Θ(n²)(每次复制整个数组 n 个元素,合并时复制 2 次),主方法情况 3,解 =Θ(n²)。
    • 策略 3:复制子数组(时间 =Θ(q-p+1)):递归式:T (n)=2T (n/2)+Θ(n)(合并时复制子数组规模 n),解 =Θ(n lg n)。
答案
算法参数传递策略递归式渐近解
二分查找指针传递T(n)=T(n/2)+Θ(1)Θ(lg n)
二分查找复制数组T(n)=T(n/2)+Θ(n)Θ(n)
二分查找复制子数组T(n)=T(n/2)+Θ(n)Θ(n)
归并排序指针传递T(n)=2T(n/2)+Θ(n)Θ(n lg n)
归并排序复制数组T(n)=2T(n/2)+Θ(n²)Θ(n²)
归并排序复制子数组T(n)=2T(n/2)+Θ(n)Θ(n lg n)

4-3 更多递归式例子(渐近上界和下界)

题目

对下列每个递归式,给出 T (n) 的渐近上界和下界。假定对足够小的 n,T (n) 是常数。a. T(n)=4T(n/3)+n lg nb. T(n)=3T(n/3)+n/lg nc. T(n)=4T(n/2)+n²√nd. T(n)=3T(n/3-2)+n/2e. T(n)=2T(n/2)+n/lg nf. T(n)=T(n/2)+T(n/4)+T(n/8)+ng. T(n)=T(n-1)+1/nh. T(n)=T(n-1)+lg ni. T(n)=T(n-2)+1/lg nj. T(n)=√n T(√n)+n

求解过程

a. T(n)=4T(n/3)+n lg n

  • a=4,b=3,log_3 4≈1.26,f(n)=n lg n=Ω(n^{1.26+ε})(ε=0.74);
  • 正则条件:4f (n/3)=4×(n/3 lg (n/3))=4n lg (n/3)/3 ≤c n lg n(c=4/3<1),情况 3;
  • 界:Θ(n lg n)。

b. T(n)=3T(n/3)+n/lg n

  • a=3,b=3,log_3 3=1,f(n)=n/lg n=o(n);
  • 代入法:T (n)=3T (n/3)+n/lg n = 求和(从 i=0 到 log3 n-1)(n/lg (n/3^i))≈n lg lg n;
  • 界:Θ(n lg lg n)。

c. T(n)=4T(n/2)+n²√n

  • a=4,b=2,log_2 4=2,f(n)=n²√n=n2.5=Ω(n^{2+ε})(ε=0.5);
  • 正则条件:4f (n/2)=4×(n2.5/(22.5))≈0.7n2.5 ≤c f (n),情况 3;
  • 界:Θ(n2.5)。

d. T(n)=3T(n/3-2)+n/2

  • 忽略 - 2,递归式≈3T (n/3)+n/2,a=3,b=3,log3 3=1,f (n)=n/2=Θ(n),情况 2;
  • 界:Θ(n lg n)。

e. T(n)=2T(n/2)+n/lg n

  • a=2,b=2,log2 2=1,f(n)=n/lg n=o(n);
  • 代入法:T (n)=2T (n/2)+n/lg n≈n lg lg n;
  • 界:Θ(n lg lg n)。

f. T(n)=T(n/2)+T(n/4)+T(n/8)+n

  • 递归树每层总代价≈n,层数≈log2 n,总代价≈n lg n;
  • 界:Θ(n lg n)。

g. T(n)=T(n-1)+1/n

  • 求和:T (n)= 求和(从 k=1 到 n)1/k=Hn(调和级数)≈ln n;
  • 界:Θ(lg n)。

h. T(n)=T(n-1)+lg n

  • 求和:T (n)= 求和(从 k=1 到 n)lg k≈n lg n;
  • 界:Θ(n lg n)。

i. T(n)=T(n-2)+1/lg n

  • 求和:T (n)= 求和(从 k=1 到 n/2)1/lg (2k)≈(1/2) ln lg n;
  • 界:Θ(lg lg n)。

j. T(n)=√n T(√n)+n

  • 令 n=2^m,T (2^m)=2^(m/2) T (2^(m/2))+2^m,定义 S (m)=T (2^m)/2^m,得 S (m)=S (m/2)+1;
  • S (m)=lg m,故 T (2^m)=2^m lg m→T (n)=n lg lg n;
  • 界:Θ(n lg lg n)。
答案

a. Θ(n lg n);b. Θ(n lg lg n);c. Θ(n2.5);d. Θ(n lg n);e. Θ(n lg lg n);f. Θ(n lg n);g. Θ(lg n);h. Θ(n lg n);i. Θ(lg lg n);j. Θ(n lg lg n)。

4-4 斐波那契数(生成函数)

题目

用生成函数技术求解斐波那契递归式 F₀=0,F₁=1,F_i=F_{i-1}+F_{i-2}(i≥2),证明 F_i=⌊φⁱ/√5 + 1/2⌋(φ=(1+√5)/2)。

求解过程
  1. 生成函数定义:斐波那契生成函数 F (z)= 求和(从 i=0 到∞)F_i z^i=0+z+z²+2z³+3z⁴+5z⁵+…。

  2. 推导 F (z) 的闭合形式

    • F(z)=z + z² + 2z³ + 3z⁴ + 5z⁵ +…
    • zF(z)=z² + z³ + 2z⁴ + 3z⁵ +…
    • z²F(z)=z³ + z⁴ + 2z⁵ +…
    • 相减:F (z)-zF (z)-z²F (z)=z → F (z)=z/(1-z-z²)。
  3. 部分分式分解:分母 1-z-z²=(1-φ z)(1-φ' z),其中 φ=(1+√5)/2,φ'=(1-√5)/2,因此:F(z)=1/√5 × [1/(1-φ z) - 1/(1-φ' z)]。

  4. 展开为幂级数:利用 1/(1-az)= 求和(从 i=0 到∞)a^i z^i,展开得:F (z)=1/√5 × [求和(从 i=0 到∞)φ^i z^i - 求和(从 i=0 到∞)φ'^i z^i] = 求和(从 i=0 到∞)(φ^i - φ'^i)/√5 z^i。因此 F_i=(φ^i - φ'^i)/√5。

  5. 近似与取整:|φ'|=(√5-1)/2≈0.618<1,故 |φ'^i|/√5<1/2,因此:F_i=φ^i/√5 - φ'^i/√5 ⇒ φ^i/√5 - 1/2 < F_i < φ^i/√5 + 1/2。由此可知 F_i 是最接近 φ^i/√5 的整数,即 F_i=⌊φ^i/√5 + 1/2⌋。

答案

通过生成函数推导得 F_i=(φ^i - φ'^i)/√5,因 |φ'^i|/√5<1/2,故 F_i=⌊φ^i/√5 + 1/2⌋,结论成立。

4-5 芯片检测(超过 n/2 好芯片)

题目

n 片芯片,好芯片能准确检测其他芯片,坏芯片检测结果任意。a. 证明:若超过 n/2 芯片是坏的,无法确定好芯片;b. 若超过 n/2 是好的,证明⌊n/2⌋次逐对检测可减半问题规模;c. 用⌊n/2⌋次检测,证明可在 Θ(n) 次检测内找到好芯片。

求解过程

a. 超过 n/2 坏芯片→无法确定好芯片

  • 坏芯片可合谋:对任意芯片 x,坏芯片一致声称 x 是坏的,好芯片(若存在)声称 x 是好的;
  • 由于坏芯片数量 > n/2,多数检测结果认为 x 是坏的,无法区分 x 是好是坏,故无法确定好芯片。

b. 超过 n/2 好芯片→⌊n/2⌋次检测减半规模

  • 逐对检测芯片 (i,i+1)(i=1,3,5,…):
    • 若检测结果为 “都好” 或 “都坏”,保留其中一个芯片;
    • 若检测结果为 “一好一坏”,丢弃这两个芯片;
  • 证明保留的好芯片 > 坏芯片:设好芯片数 G>n/2,坏芯片数 B=n-G<n/2。
    • 好 - 好对:G 中选 2 个,共 C (G,2) 对,保留的好芯片数≥C (G,2);
    • 坏 - 坏对:B 中选 2 个,共 C (B,2) 对,保留的坏芯片数≤C (B,2);
    • 好 - 坏对:G×B 对,丢弃,不影响保留芯片;由于 G>B,保留的好芯片数 > 坏芯片数,问题规模减半(保留芯片数≤n/2)。

c. 递归式与 Θ(n) 检测

  • 递归式:T (n)=T (⌊n/2⌋)+⌊n/2⌋(每次检测⌊n/2⌋次,规模减半);
  • 展开递归式:T (n)=⌊n/2⌋+⌊n/4⌋+…+1=O (n),故总检测次数为 Θ(n)。
答案

a. 坏芯片合谋导致多数检测结果错误,无法确定好芯片;b. 逐对检测保留好芯片 > 坏芯片,规模减半;c. 递归式 T (n)=T (⌊n/2⌋)+⌊n/2⌋的解为 Θ(n),故可在 Θ(n) 次检测内找到好芯片。

4-6 Monge 阵列(性质与算法)

题目

Monge 阵列 A 满足:对 1≤i<k≤m,1≤j<l≤n,A [i][j]+A [k][l]≤A [i][l]+A [k][j]。a. 证明:A 是 Monge 阵列当且仅当对所有 i,j,A [i][j]+A [i+1][j+1]≤A [i][j+1]+A [i+1][j];b. 修改数组为 Monge 阵列;c. 证明:第 i 行最左最小元素列下标 f (i) 非递减;d. 分治算法:用 O (m+n) 时间计算奇数行最左最小元素(已知偶数行);e. 递归式 T (m,n)=T (m/2,n)+O (m+n),解为 O (m+n lg m)。

求解过程

a. 充要条件证明

  • 必要性:取 k=i+1,l=j+1,直接满足 Monge 阵列的定义;
  • 充分性:用归纳法,对 k-i 和 l-j 的差值归纳。假设对 k-i=1、l-j=1 成立,扩展到 k>i+1、l>j+1:由 A [i][j]+A [i+1][j+1]≤A [i][j+1]+A [i+1][j],A [i+1][j]+A [i+2][j+1]≤A [i+1][j+1]+A [i+2][j],两式相加消去 A [i+1][j] 和 A [i+1][j+1],得 A [i][j]+A [i+2][j+1]≤A [i][j+1]+A [i+2][j],以此类推可扩展到任意 k>i、l>j。

b. 修改数组为 Monge 阵列

  • 原非 Monge 数组:[[37,23,22,32],[21,6,7,10],[53,34,30,31],[32,13,9,6],[43,21,15,8]]
  • 检查关键位置:A [3][2]=34,计算 A [2][1]+A [3][2]=21+34=55,A [2][2]+A [3][1]=6+53=59,55≤59(满足);A [3][2]+A [4][3]=34+9=43,A [3][3]+A [4][2]=30+21=51,43≤51(满足);
  • 唯一需修改的位置:A [1][1]+A [3][4]=37+31=68,A [1][4]+A [3][1]=32+53=85(满足);实际发现 A [4][1]+A [5][2]=32+21=53,A [4][2]+A [5][1]=13+43=56(满足),最终修改 A [3][2] 为 33(原 34),验证所有相邻位置满足 Monge 性质,数组变为 Monge 阵列。

c. f (i) 非递减证明

  • 反证法:假设存在 i 使 f (i)>f (i+1),取 j=f (i+1),l=f (i)(j<l);
  • 由 Monge 性质:A [i][j]+A [i+1][l]≤A [i][l]+A [i+1][j];
  • 因 f (i) 是第 i 行最左最小值,A [i][j]≥A [i][l];
  • 因 f (i+1) 是第 i+1 行最左最小值,A [i+1][l]≥A [i+1][j];
  • 故 A [i][j]+A [i+1][l]≥A [i][l]+A [i+1][j],结合 Monge 性质得等号,因此 f (i)≤f (i+1),即 f (i) 非递减。

d. O (m+n) 计算奇数行最左最小元素

  • 已知偶数行 f (2),f (4),…,f (m),由 c 的结论,奇数行 i 的最左最小元素列下标 f (i)∈[f (i-1),f (i+1)](因 f (i-1)≤f (i)≤f (i+1));
  • 对每个奇数行 i,仅需在 [f (i-1),f (i+1)] 范围内遍历找最小值,总遍历次数≤n(所有行的搜索范围覆盖列数不超过 n),加行遍历时间 O (m),总时间 O (m+n)。

e. 递归式求解

  • 递归式 T (m,n)=T (m/2,n)+O (m+n);
  • 展开:T (m,n)=O (m+n) + O (m/2+n) + O (m/4+n) + … + O (1+n);
  • 求和:O (m + m/2 + … +1) + O (n lg m) = O (m) + O (n lg m) = O (m + n lg m)。
答案

a. 必要性直接取 k=i+1、l=j+1,充分性用归纳法;b. 修改 A [3][2] 为 33,数组变为 Monge 阵列;c. 反证法结合 Monge 性质,得 f (i) 非递减;d. 利用 f (i)∈[f (i-1),f (i+1)],总时间 O (m+n);e. 递归式解为 O (m + n lg m)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值