递归树(Recursion Tree)方法是解决递归式的一种可视化方法,通过图形化展示递归的展开过程,从而帮助推导递归式的时间复杂度。递归树方法通过逐层展开递归过程来累加每一层的工作量,从而得出总的工作量。
递归树方法的步骤
- 展开递归式:将递归式逐层展开,直到递归到基本情况(通常是常数时间)。
- 计算每一层的工作量:在每一层中,计算当前层的工作量(通常是 O(n)O(n) 这样的多项式级别)。
- 计算树的高度:树的高度取决于递归的深度。
- 计算总工作量:总工作量是各层的工作量之和。
示例:T(n)=2T(n/2)+nT(n) = 2T(n/2) + n
我们通过递归树来求解这个递归式。
步骤 1:展开递归式
递归式 T(n)=2T(n/2)+nT(n) = 2T(n/2) + n 描述了一个分治型问题,其中每次将问题分成两个子问题,每个子问题的规模是原问题的一半,而每次合并的工作量是线性的,即 O(n)O(n)。
我们从根节点开始,递归树展开的第一层是 T(n)=2T(n/2)+nT(n) = 2T(n/2) + n。
接下来展开递归式:
- 第二层:每个 T(n/2)T(n/2) 又会继续展开,得到两个 T(n/4)T(n/4),因此第二层有 4 个节点,每个节点的工作量是 n/2n/2,所以总工作量是 2×(n/2)=n2 \times (n/2) = n。
- 第三层:每个 T(n/4)T(n/4) 又会继续展开,得到 8 个 T(n/8)T(n/8),每个节点的工作量是 n/4n/4,所以第三层的总工作量也是 nn。
如此继续展开,直到递归到基本情况 T(1)T(1)。
步骤 2:绘制递归树
我们可以将递归树表示为以下结构:
Level 0: n
Level 1: n/2 n/2
Level 2: n/4 n/4 n/4 n/4
Level 3: n/8 n/8 n/8 n/8 n/8 n/8 n/8 n/8
...
每一层的工作量如下:
- Level 0:只有一个节点,工作量为 nn。
- Level 1:有两个节点,每个节点的工作量为 n/2n/2,所以总工作量为 2×n/2=n2 \times n/2 = n。
- Level 2:有四个节点,每个节点的工作量为 n/4n/4,所以总工作量为 4×n/4=n4 \times n/4 = n。
- Level 3:有八个节点,每个节点的工作量为 n/8n/8,所以总工作量为 8×n/8=n8 \times n/8 = n。
- ...
步骤 3:计算递归树的高度
递归树的高度是树中层数的数量。每次递归将问题规模减半,因此树的高度为 log2n\log_2 n 层。每一层的节点数是前一层的两倍,直到递归到最底层,即当问题规模减小到 1 时,树的高度为 log2n\log_2 n。
步骤 4:计算总工作量
- 每一层的工作量都是 O(n)O(n)。
- 总工作量是各层工作量的总和。树的高度是 log2n\log_2 n,每一层的工作量是 nn,因此总的工作量为: T(n)=n+n+n+⋯+n(log2n 层)T(n) = n + n + n + \cdots + n \quad (\log_2 n \text{ 层}) 也就是 T(n)=O(nlogn)T(n) = O(n \log n)。
结果
通过递归树法,我们得出结论:
T(n)=O(nlogn)T(n) = O(n \log n)
这就是该递归式的时间复杂度。
另一个示例:T(n)=3T(n/2)+nT(n) = 3T(n/2) + n
我们再通过递归树求解另一个递归式:
步骤 1:展开递归式
递归式 T(n)=3T(n/2)+nT(n) = 3T(n/2) + n 描述了每次将问题分成三个子问题,且每次合并的工作量是线性的。
- 第一层:工作量是 nn。
- 第二层:每个 T(n/2)T(n/2) 会分成三个 T(n/4)T(n/4),所以第二层有 3 个节点,每个节点的工作量是 n/2n/2,总工作量为 3×(n/2)=3n/23 \times (n/2) = 3n/2。
- 第三层:每个 T(n/4)T(n/4) 会分成三个 T(n/8)T(n/8),所以第三层有 9 个节点,每个节点的工作量是 n/4n/4,总工作量为 9×(n/4)=9n/49 \times (n/4) = 9n/4。
递归树继续扩展,直到递归到基本情况。
步骤 2:绘制递归树
Level 0: n
Level 1: n/2 n/2 n/2
Level 2: n/4 n/4 n/4 n/4 n/4 n/4 n/4 n/4
...
步骤 3:计算递归树的高度
递归树的高度是 log2n\log_2 n,与上一例相同。
步骤 4:计算总工作量
在每一层,节点数增长为 3k3^k,每个节点的工作量是 n/2kn / 2^k,因此第 kk 层的工作量为:
3k×n2k=n(32)k3^k \times \frac{n}{2^k} = n \left( \frac{3}{2} \right)^k
总工作量是所有层的工作量之和,即:
T(n)=n∑k=0log2n(32)kT(n) = n \sum_{k=0}^{\log_2 n} \left( \frac{3}{2} \right)^k
这个级数是一个等比级数,其和的上界为 O(n)O(n),因此:
T(n)=O(nlog23)≈O(n1.585)T(n) = O(n^{\log_2 3}) \approx O(n^{1.585})
这就是递归式 T(n)=3T(n/2)+nT(n) = 3T(n/2) + n 的时间复杂度。
总结
递归树方法通过可视化递归的展开过程,帮助我们理解每一层的工作量并求解递归式的时间复杂度。每一层的工作量通常是根据递归式的系数来计算的,树的高度由问题的规模决定。对于常见的递归式,递归树方法通常能够直观地得出复杂度结果。