第一部分:分治法的核心思想与识别
这是你在机试中面对未知题目时,判断是否应该使用分治法的关键。
1. 什么是分治法?
分治法是一种解决问题的通用范式。它的核心思想是:将一个难以直接解决的大问题,分割成若干个规模较小的、相互独立的、与原问题形式相同的子问题,然后递归地去解决这些子问题。最后,将各个子问题的解合并,从而得到原问题的解。
可以记下这三个标志性的步骤:
- 分解 (Divide): 将原问题分解为一系列子问题。
- 解决 (Conquer): 递归地求解各个子问题。若子问题足够小,则直接求解。
- 合并 (Combine): 将子问题的解合并成原问题的解。
2. 如何在机试中识别分治法题目?
当你看到一个问题,可以试着问自己以下几个问题:
- 这个问题的输入数据(例如数组、点集)能否被“一分为二”?
- 如果我已经解决了左半部分和右半部分,我能否通过一些相对简单的操作,将这两个答案合并成最终答案?
- 这个“合并”操作的复杂度是否比暴力求解整个问题的复杂度要低?
如果答案都是“是”,那么这道题很可能就是分治法的用武之地。例如,排序问题、在有序数组中查找、求解最大子数组等,都具有鲜明的“可分”和“可合”的特性。
第二部分:通用时间复杂度分析 (笔试重点)
分治算法的运行时间通常通过解递归关系式来确定。掌握它,笔试中的分析题就迎刃而解了。
通用形式为: T(n)=aT(n/b)+f(n)T(n) = aT(n/b) + f(n)T(n)=aT(n/b)+f(n)
- nnn: 问题规模
- aaa: 递归产生的子问题数量
- n/bn/bn/b: 每个子问题的规模
- f(n)f(n)f(n): 分解问题和合并解所需的时间
常见结论 (主定理的简化形式):
-
T(n)=2T(n/2)+O(n)T(n) = 2T(n/2) + O(n)T(n)=2T(n/2)+O(n) ⇒\Rightarrow⇒ T(n)=O(nlogn)T(n) = O(n \log n)T(n)=O(nlogn)
- 解释: 每次把问题分成2个规模为一半的子问题,合并需要 O(n)O(n)O(n) 时间。
- 经典例子: 归并排序、最大子数组问题、二维极大点。
-
T(n)=T(n/2)+O(1)T(n) = T(n/2) + O(1)T(n)=T(n/2)+O(1) ⇒\Rightarrow⇒ T(n)=O(logn)T(n) = O(\log n)T(n)=O(logn)
- 解释: 每次把问题规模缩小一半,分解和合并都是常数时间。
- 经典例子: 二分检索。
-
T(n)=2T(n/2)+O(1)T(n) = 2T(n/2) + O(1)T(n)=2T(n/2)+O(1) ⇒\Rightarrow⇒ T(n)=O(n)T(n) = O(n)T(n)=O(n)
- 解释: 每次分成2个子问题,但合并是常数时间。
- 经典例子: 寻找最大最小元素。
-
T(n)=aT(n/b)+O(nd)T(n) = aT(n/b) + O(n^d)T(n)=aT(n/b)+O(nd)
- 若 a>bda > b^da>bd, 则 T(n)=O(nlogba)T(n) = O(n^{\log_b a})T(n)=O(nlogba) (例如斯特拉森矩阵乘法)
- 若 a=bda = b^da=bd, 则 T(n)=O(ndlogn)T(n) = O(n^d \log n)T(n)=O(ndlogn) (例如归并排序)
- 若 a<bda < b^da<bd, 则 T(n)=O(nd)T(n) = O(n^d)T(n)=O(nd)

最低0.47元/天 解锁文章
6894

被折叠的 条评论
为什么被折叠?



