分治算法

分治算法

一 基本概念

《算法导论》中,提到:许多有用的算法在结构上都是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关的若干子问题。这些算法典型地遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解。(分解–解决–合并)

在计算机科学中,分治法是一种很重要的算法,能大大降低算法的时间复杂度。但其Divide–Conquer–Combine的思想其实很简单。分而治之的思想是很多高效算法的基础,如排序算法(快速排序,归并排序),二叉树遍历,傅立叶变换(快速傅立叶变换)……

任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。问题的规模越小,越容易直接求解,解题所需的计算时间也越少。例如,对于n个元素的排序问题,当n=1时,不需任何计算。n=2时,只要作一次比较即可排好序。n=3时只要作3次比较即可,…。而当n较大时,问题就不那么容易处理了。要想直接解决一个规模较大的问题,有时是相当困难的。

二 策略

分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计策略叫做分治法。

如果原问题可分割成k个子问题,1 < k ≤ n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。

三 分治法适用的情况

分治法所能解决的问题一般具有以下几个特征:

1) 该问题的规模缩小到一定的程度就可以容易地解决

2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质

3) 利用该问题分解出的子问题的解可以合并为该问题的解

4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题

第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;

第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;

第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法

第四条特征涉及到分治法的效率如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好

四 分治法的基本步骤

分治法在每一层递归上都有三个步骤:

  1. Divide:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题(注意,子问题最好具有相等的规模,事实上,一般也是这样来分的,而且分为两个实例的居多);
  2. Conquer:若子问题的规模较小而容易被解决则直接解,否则递归地解决各个子问题;
  3. Combine:将各个子问题的解合并为原问题的解(事实上,一个分治算法的精华在于合并解的过程)。

分治法的一般的算法设计模式如下:

Divide-and-Conquer(P)
1. if |P| ≤n0
2. then return (ADHOC(P))
3. 将P分解为较小的子问题P1, P2, …, Pk
4. for i <– 1 to k
5. do yi <– Divide-and-Conquer(Pi)△ 递归解决Pi
6. T <– MERGE(y1, y2, …, yk) △ 合并子问题
7. return(T)

其中|P|表示问题P的规模;n0为一阈值,表示当问题P的规模不超过n0时,问题已容易直接解决,不必再继续分解。ADHOC(P)是该分治法中的基本子算法,用来直接解规模较小的问题P。因此,当P的规模不超过n0时直接用算法ADHOC(P)求解。算法MERGE(y1, y2, …, yk)是该分治法中的合并子算法,用于将P的子问题P1,P2, …, Pk的解合并成P的解。

五 分治法的复杂性分析

一个分治法将规模为n的问题划分为b个规模为n/b的实例,其中a个实例是需要求解的,用f(n)表示将求解得到的a个子问题的解合并起来的时间复杂度。则有:

T(n) = aT(n/b)+f(n)

可以根据主定理求解该算法的时间复杂度。

这里写图片描述

这里对主定理做一些分析:

  1. 这个式子是一个通用的数学表达式,在计算机的常用算法策略中,它太概括了,我们往往用到的只是它范围很小的一部分。

    • a和b的关系,其实a绝大多数时候都是等于b的(因为规模n划分为了b个子规模,需要处理的是a个),a,b的含义告诉我们a <= b(当这是最基本要满足的条件)。常常要么是 a==b(分成的子规模都要处理,然后去合并),要么是a==1(实际上这是减治的思想,分成了b个子规模,但最终却可以排除其他的,只在其中一个子规模中去处理)。一般来说就是这样,所以a,b并不是随意的。

    • 其实b要么为2(几乎所有情况)要么为3(极少数情况),这个分治思想里面就说啦,一般来说都是分为2个规模相等的子规模(当然谁都想分的越多越好,这样算法就更快,但是现实是问题往往没有那么高效的算法,找到一个3的分治就已经很不错了)

    • f(n)是线性的的情况很多(即d=1的情况是最多的)。再来看看a和b^d比较大小的关系说明了什么:f(n)代表的是合并的复杂度,1<=a <= b,定性的分析,可以知道:

      • a < b^d
        因为1<=a <= b,所以只要d>1,不管a,b是什么(不管怎么划分规模,也不管需要处理几个规模),总是第一种情况,时间复杂度是n^d。如果d=1呢,只要a < b(处理的比划分的少),那么还是第一种情况,时间复杂度也是n^d = n

      • a = b^d
        因为1<=a <= b,所以如果a=b(划分多少处理多少),那么d只能为1才能是这种情况。—–常见的归并排序都是这样
        而如果a < b,那d就只能<1才能是这种情况,一般很少见。

      • a > b^d
        非常少见,我还木有见过这样的算法,一开始我认为这种情况不可能,但在理论上它是存在的。因为1<=a <= b,所以要满足这个式子d必须<1 。

      • 从这也可以看出这三个参数之间的关系,事实上是划分的复杂度和合并的复杂度在争抢复杂度的控制权

    • 说了这么多,感觉越分析越复杂了吗,其实不是,把这些分析想清楚,对递推式的理解就更进一步了,有了上述分析,其实下面几个常见的递推式就包含了大多数的算法。T(n) = a * T(n/b) + f(n)的常见式子:

      • T(n) = 2 * T(n/2) + O(n)      
        时间复杂度n*log(n)。一般来说分治算法就是这样,分成2个子规模的问题,需要处理的也是2个,对这两个子规模合并又是线性的
        a = b = 2, d = 1; a == b^d 由主定理得n*log(n)。只要a=b,d=1,就都是这个复杂度。

      • T(n) = T(n/2) + O(n)        
        时间复杂度为n,线性的。a = 1,b = 2,d=1(分为2个子规模,但只对一个子规模处理,合并也是线性的)。a < b^d, 时间复杂度是n^d = n。其实只要a < b,d=1,都是这个。

感觉对一个定理解读了这么多,确实让它变得更加复杂了,但如果你做了上述思考,相信对这个式子认识也更加深刻了一点。当然,如果你觉得直接记住上面这个公式就可以了,可以无视以上解读。

六 可使用分治法求解的一些经典问题

  1. 二分搜索
  2. 大整数乘法
  3. Strassen矩阵乘法
  4. 棋盘覆盖
  5. 合并排序
  6. 快速排序
  7. 线性时间选择
  8. 最接近点对问题
  9. 循环赛日程表
  10. 汉诺塔

七 依据分治法设计程序时的思维过程

实际上就是类似于数学归纳法,找到解决本问题的求解方程公式,然后根据方程公式设计递归程序。
1. 一定是先找到最小问题规模时的求解方法
2. 然后考虑随着问题规模增大时的求解方法
3. 找到求解的递归函数式后(各种规模或因子),设计递归程序即可。

这篇博文基本复制的下面一篇文章:
http://www.cnblogs.com/steven_oyj/archive/2010/05/22/1741370.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值