PrepStack · Markdown HTML

分治:拆分、递归、合并

分治与归并计数 · HTML

数学 / 逻辑形态

T(n)=aT(n/b)+C(n)。split 定义子域,solve 返回最小充分摘要,combine 由子摘要构造父答案;基础规模直接求解。

识别信号

容易误判的相似信号

SignalWhy it is different
子问题大量重叠同一状态反复出现时应 memoization/DP,纯分治会指数重复。
combine 比原问题还难若每层合并重新做 O(n²),拆分未带来收益。
仅仅用了递归递归是控制流;分治还需独立子问题与明确合并契约。

核心不变量

solve(lo,hi) 返回该子域完整且符合约定的摘要;combine 只依赖子摘要,并使每个跨子域贡献恰计一次。

状态、转移与处理顺序

ItemDefinition
State当前半开子域 [lo,hi)、其返回摘要,以及可复用的临时缓冲。
Transitionbase case 直接返回;否则 split,递归求子摘要,再 combine。
Frontier / order递归栈上的待求解/待合并子域,通常按 postorder 完成。

Python 骨架

def divide_solve(items):
    def solve(lo, hi):
        if hi - lo <= 1:
            return items[lo:hi]
        mid = lo + (hi - lo) // 2
        left = solve(lo, mid)
        right = solve(mid, hi)
        merged, i, j = [], 0, 0
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                merged.append(left[i]); i += 1
            else:
                merged.append(right[j]); j += 1
        return merged + left[i:] + right[j:]
    return solve(0, len(items))

正确性思路

  1. 基础规模按定义正确。
  2. 归纳假设每个子调用返回其子域完整摘要。
  3. combine 契约保留内部答案并补齐跨边界贡献,所以父域正确;归纳至根。

复杂度

TimeSpaceParameters
由 T(n)=aT(n/b)+C(n) 决定;二分加线性合并为 O(n log n)典型 O(n) 缓冲 + O(log n) 栈a 为子问题数,b 为缩小因子,C(n) 为合并成本。

边界条件

错误模式

PatternWhy it fails / fix
区间约定混乱统一 [lo,hi),base 为 hi-lo<=1,避免 mid 重叠或遗漏。
每层切片复制可能放大空间与常数;性能敏感时传边界并复用 buffer。
未定义返回契约父层不知道子摘要语义,combine 必然脆弱。
错误套 Master Theorem子问题不均或成本不规则时应画递归树分析。

选择与排除规则

相关模板

RelationTemplateBoundary
contrast交换论证 / 局部最优排序分治靠子问题合并,交换贪心靠局部次序替换。
contrast区间 DP分割点固定/子问题独立时分治;需枚举所有分割时 DP。
结构基础线段树区间聚合理解区间拆分与摘要合并
structural-analogy树递归聚合 / 后序返回值输入天然为树,父节点合并子树摘要。

原创微型例子

环节内容
Result每层总合并 O(7),共有约 log 7 层。
Setup把 7 个读数按位置分成左右两半并排序。
Trace递归让两半有序,合并只比较各自尚未消费的最小头部。

Recall prompts

我的补充