算法分析——分治法
分治算法
小组的汇报内容:
一、分治算法的基本概念 (2)
二、分治算法的基本思想及策略 (2)
三、分治法适用的情况 (3)
四、分治法的基本步骤 (3)
五、分治法的复杂性分析 (4)
六、快速傅里叶变换 (5)
七、可使用分治法求解的一些经典问题 (9)
八、依据分治法设计程序时的思维过程 (9)
九、分治法与其它常见算法的比较 (9)
小组的分工情况:
彭勇讲前五个部分,天西山讲第六个部分,胡化腾讲最后三个部分,吕璐负责汇报的资料收集,小组分工以及最后的资料整理。
三、分治法适用的情况
分治法所能解决的问题一般具有以下几个特征:
1) 该问题的规模缩小到一定的程度就可以容易地解决
2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
3) 利用该问题分解出的子问题的解可以合并为该问题的解;
4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;
第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;、
第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。
第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。
四、分治法的基本步骤
分治法在每一层递归上都有三个步骤:
step1 分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
step2 解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
step3 合并:将各个子问题的解合并为原问题的解。
它的一般的算法设计模式如下:
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的相应的解y1,y2,...,yk合并为P的解。
五、分治法的复杂性分析
一个分治法将规模为n的问题分成k个规模为n/m的子问题去解。设分解阀值n0=1,且adhoc解规模为1的问题耗费1个单位时间。再设将原问题分解为k个子问题以及用merge将k个子问题的解合并为原问题的解需用f(n)个单位时间。用T(n)表示该分治法解规模为|P|=n的问题所需的计算时间,则有: T(n)= k T(n/m)+f(n)
通过迭代法求得方程的解:
递归方程及其解只给出n等于m的方幂时T(n)的值,但是如果认为T(n)足够平滑,那么由n等于m的方幂时T(n)的值可以估计T(n)的增长速度。通常假定T(n)是单调上升的,从而当mi≤n 在了解这个算法之前,我们首先必须弄清楚这样几个问题。什么是傅里叶变换?什么是快速傅里叶变换? 傅里叶变换能将满足一定条件的某个函数表示成三角函数(正弦和/或余弦函数)或者它们的积分的线性组合。在不同的研究领域,傅里叶变换具有多种不同的变体形式,如连续傅里叶变换和离散傅里叶变换。最初傅里叶分析是作为热过程的解析分析的工具被提出的。离散傅里叶变换的一种快速算法。所以我们可以了解到快速傅里叶变换就是对离散的点进行处理的算法。今天我们通过两个多项式的乘积来介绍FFT。 S=P X?K(X) S=(P O+P1X+P2X2+?+P n?1X n?1)?(K0+K1X+K2X2+?+ K n?1X n?1) 在上个式子中,我们得到S是最高阶位2N-2。我们知道一次函数可以通过二个点来确定这个函数,二次函数可以通过三个点来确定,三次函数可以通过四个点来确定。由此我们可以推想S可以由2N-1个点上的值确定,事实上也确实如此,证明过程大家下去在研究。这2N-1个点上的值可以通过两个多项式在这些点上的值相乘而得到。由此我们得到两个N-1阶多项式相乘的一般方法,如下所示: (1)计算给定的两个多项式在2N-1个不同点上的值。 (2)在没一点上将两值相乘。 (3) 根据这2N-1个点上的乘积,用内插法求出乘积多项式。 我们来计算这个算法的时间复杂度,可以得知其时间复杂度是N 2级别的。当N 很大时,已不能满足计算要求。必须寻找新的算法来解决这个问题。 下面我向大家介绍用快速傅里叶变换算法解决两个多项式的乘法问题,在算法中用到的思想就是分治的思想。 我们注意到刚才在用2N-1个点计算多项式成绩时,没有特别指定是什么点,只要他们在定义域内即可。这样,如果我们选取特点的2N-1个点,那么就有可能使计算多项式的值和内插变得容易。 可以选取1的复数跟W n 0、W n 1、…、W n n ?1来充当这些点。因为1的复数跟 具有周期变化的性质,所以这给计算带来了方便。可能大家已经忘记1的复数跟的表达形式了,我简要给大家介绍一下。 W n 0=cos 2kπ n +sin 2kπ n i (k=0、1、2……n-1) 这就是1的复数跟形式,具有周期性变化。我们就来验证一下。比如我们取一个多项式最高阶是7,那么它的复数跟就是。 W 80=1、W 81= 22+ 22i 、W 82=i 、W 83=? 22+ 22i W 84=1、W 85=?( 22+ 22i )、W 86=-i 、W 87=?(? 22+ 22 i ) 首先考虑用分治法计算多项式在1的复数跟上的值。即要计算多项式 S =(P O +P 1X +P 2X 2+?+P n ?1X n ?1)在点W n 0、W n 1、…、W n n ?1上的 值,表示为 y k = (n?1 i =0w n k )i p i ,0<=k 这时,(y 0、y 1、y 2…、y n ?1)称为(p 0、p 1、p 2…、p n ?1)的离散傅里叶变换,(p 0、p 1、p 2…、p n ?1)称为(y 0、y 1、y 2…、y n ?1)的傅里叶逆变换。 现在用法求多项式在W n k (0<=k 次幂和奇次幂两个子多项式。如n=8,则有 P X =P O +P 1X +P 2X 2+?+P 7X 7 =P O +P 2X 2+P 4X 4+P 6X 6+X (P 1+P 3X 2+P 5X 4+P 7X 6) =P (X 2)+P 0(X 2) 若X 是1的复数根,则X 2也是1的复数根。即设X=W 80,则X 2=W 41,X 4= W 42,X 3=W 43,这个计算带来了方便。 若n 是偶数,X 是1的n 次复数根,那么X 2必是1的n/2次方根,又由于P 0(X 2)和P (X 2)是n/2-1阶多项式,所以对P 0(X 2)和P (X 2)只要计算n/2个1的n/2次方根,从而节约了计算量。 比如计算7阶多项式,用一般方法就要计算P (x )在1的8次方根W 8,可以表示为如下: W 8:W 80、W 81、W 82、W 83、?W 80、?W 81、?W 82、?W 83、 他们的平方是1的4次方根: W 82:W 40、W 41、W 42、W 43、W 40、W 41、W 42、W 43 用分治法计算P (X )在n 个1的n 次方根上的值 P W n k =P(W n 2k )+P 0 (W n 2 k ) 如7次多项式在8个1的8次方根上的值为: P W 80 =P W 40 +W 80P 0 W 40 P W 81 =P W 41 +W 81P 0 W 41 P W 82 =P W 42 +W 82P 0 W 42 P W83=P W43+W83P0W43 P W84=P W44?W80P0W44 P W85=P W45?W81P0W45 P W86=P W46?W82P0W46 P W87=P W47?W83P0W47 设P(X)是n-1阶多项式,M(n)是计算P(X)在n个点上的值所需要的乘 法次数,M(n 2)是计算n 2 ?1阶多项式在n 2 个点上的值所需要的乘法次数。由以上 讨论可得如下的地推关系式: M(n)=2 M(n 2)+ n 2 (其中n 2 是求X?P0所需要的乘法次数。求解递归关系式 设n=2k M2k 2k = M2k?1 2k?1 + 1 2 ?2?k?2k M2k?1 =M2k?2 + 1 ?2?k+1?2k?1 …… …… …… M20 20= 1 2 ?2?0?20 M2k =1 (2?k?2k+2?k+1?2k?1+?+2?0?20) 整理得: M2k=1 2(2 0?2k+21?2k?1+?+2k?20) =1 2 ?k+1?2k =1 2 n logn+1 可得M(n)=O(nlogn)。在n值很大时,nlogn比n2节省了很多运算次数,快速傅里叶变换具有很大的优势。 七、可使用分治法求解的一些经典问题 (1)二分搜索 (2)大整数乘法 (3)Strassen矩阵乘法 (4)棋盘覆盖 (5)合并排序 (6)快速排序 (7)线性时间选择 (8)最接近点对问题 (9)循环赛日程表 (10)汉诺塔 八、依据分治法设计程序时的思维过程 实际上就是类似于数学归纳法,找到解决本问题的求解方程公式,然后根据方程公式设计递归程序。 1、一定是先找到最小问题规模时的求解方法 2、然后考虑随着问题规模增大时的求解方法 3、找到求解的递归函数式后(各种规模或因子),设计递归程序即可。 九、分治法与其它常见算法的比较 1、递归与分治法: 由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。 分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许 多高效算法。 2、动态规划法与分治法 共同点:将待求解的问题分解成若干子问题,先求解子问题,然后再从这些子问题的解得到原问题的解。 不同点: 1、适合于用动态规划法求解的问题,分解得到的各子问题往往不是相互独立的;而分治法中子问题相互独立。 2、动态规划法用表保存已求解过的子问题的解,再次碰到同样的子问题时不必重新求解,而只需查询答案,故可获得多项式级时间复杂度,效率较高;而分治法中对于每次出现的子问题均求解,导致同样的子问题被反复求解,故产生指数增长的时间复杂度,效率较低。 最接近点对问题 一.实验目的: 1.理解算法设计的基本步骤及各步的主要内容、基本要求; 2.加深对分治设计方法基本思想的理解,并利用其解决现实生活中的问题; 3.通过本次实验初步掌握将算法转化为计算机上机程序的方法。 二.实验内容: 1.编写实现算法:给定n对点,在这n对点中找到距离最短的点对。 2.将输出数据存放到另一个文本文件中,包括结果和具体的运行时间。 3.对实验结果进行分析。 三.实验操作: 1.最接近点对查找的思想: 首先,将所有的点对按照x坐标排序,找到x坐标的中位数,将所有的点对分成三部分,横坐标小于x(S1)、等于x(S2)和大于x(S3)的点对,在求取每部分中的最短距离,利用分治法,一步步地分解为子问题,找到最短距离d。由于距离最近的两个点可能在不同的区域中,需要进一步判断。 选择S1中的一个点,由于与它相比较的点的距离不可能超过d,故其配对范围为d*2d的矩形,将这个矩形划分为6份2/d*3/d的小矩形,其对角线的长度为5/6d,小于d,故S1中的任意一个点只需和S2中的6个点比较即可,最终确定最短的距离。 2.取中位数: 为了减少算法的时间开销,需要将所有的点对进行分组,以中位数为基准,考虑到快速排序的不稳定性,本次排序使用了合并排序。 代码实现: template 应用数学学院信息安全专业班学号姓名 实验题目递归与分治法 综合实验评分表 实验报告 一、实验目的与要求 1.掌握递归算法的设计思想 2.掌握分治法设计算法的一般过程 3.理解并掌握算法渐近时间复杂度的分析方法 二、实验内容 1、折半查找的递归算法 (1)源程序代码 #include if(-1 != addr) cout << endl << n << "是上述整数中的第" << addr << "个数" << endl; else cout << endl << n << "不在上述的整数中" << endl << endl; getchar(); return 0; } (2)运行界面 ①查找成功 ②查找失败 问题场景:在应用中,常用诸如点、圆等简单的几何对象代表现实世界中的实体。在涉及这些几何对象的问题中,常需要了解其邻域中其他几何对象的信息。例如,在空中交通控制问题中,若将飞机作为空间中移动的一个点来看待,则具有最大碰撞危险的2架飞机,就是这个空间中最接近的一对点。这类问题是计算几何学中研究的基本问题之一。 问题描述:给定平面上n个点,找其中的一对点,使得在n个点的所有点对中,该点对的距离最小。严格地说,最接近点对可能多于1对。为了简单起见,这里只限于找其中的一对。 1、一维最接近点对问题 算法思路: 这个问题很容易理解,似乎也不难解决。我们只要将每一点与其他n-1个点的距离算出,找出达到最小距离的两个点即可。然而,这样做效率太低,需要O(n^2)的计算时间。在问题的计算复杂性中我们可以看到,该问题的计算时间下界为Ω(nlogn)。这个下界引导我们去找问题的一个θ(nlogn)算法。采用分治法思想,考虑将所给的n个点的集合S 分成2个子集S1和S2,每个子集中约有n/2个点,然后在每个子集中递归地求其最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对,因为S1和S2的最接近点对未必就是S的最接近点对。如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解 决。但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需做n^2/4次计算和比较才能确定S的最接近点对。因此,依此思路,合并步骤耗时为O(n^2)。整个算法所需计算时间T(n)应满足:T(n)=2T(n/2)+O(n^2)。它的解为T(n)=O(n^2),即与合并步骤的耗时同阶,这不比用穷举的方法好。从解递归方程的套用公式法,我们看到问题出在合并步骤耗时太多。这启发我们把注意力放在合并步骤上。 设S中的n个点为x轴上的n个实数x1,x2,..,xn。最接近点对即为这n个实数中相差最小的2个实数。我们显然可以先将x1,x2,..,x n排好序,然后,用一次线性扫描就可以找出最接近点对。这种方法主要计算时间花在排序上,在排序算法已经证明,时间复杂度为O(nlogn)。然而这种方法无法直接推广到二维的情形。因此,对这种一维的简单情形,我们还是尝试用分治法来求解,并希望能推广到二维的情形。假设我们用x轴上某个点m将S划分为2个子集S1和S2,使得S1={x∈S|x≤m};S2={x∈S|x>m}。这样一来,对于所有p∈S1和q∈S2有p 华南农业大学期末考试试卷(A卷)2008学年第一学期考试科目:算法分析与设计 考试类型:(闭卷)考试时间:120 分钟 学号姓名年级专业 一、选择题(20分,每题2分) 1.下述表达不正确的是。 A.n2/2 + 2n的渐进表达式上界函数是O(2n) B.n2/2 + 2n的渐进表达式下界函数是Ω(2n) C.logn3的渐进表达式上界函数是O(logn) D.logn3的渐进表达式下界函数是Ω(n3) 2.当输入规模为n时,算法增长率最大的是。 A.5n B.20log 2n C.2n2 D.3nlog 3 n 3.T(n)表示当输入规模为n时的算法效率,以下算法效率最优的是。A.T(n)= T(n – 1)+1,T(1)=1 B.T(n)= 2n2 C.T(n)= T(n/2)+1,T(1)=1 D.T(n)= 3nlog 2 n 4.在棋盘覆盖问题中,对于2k×2k的特殊棋盘(有一个特殊方块),所需的L型骨 牌的个数是。 A.(4k– 1)/3 B.2k /3 C.4k D.2k 5.在寻找n个元素中第k小元素问题中,若使用快速排序算法思想,运用分治算 法对n个元素进行划分,应如何选择划分基准?下面答案解释最合理。 A.随机选择一个元素作为划分基准 B.取子序列的第一个元素作为划分基准 C.用中位数的中位数方法寻找划分基准 D.以上皆可行。但不同方法,算法复杂度上界可能不同 6.有9个村庄,其坐标位置如下表所示: 现在要盖一所邮局为这9个村庄服务,请问邮局应该盖在才能使到邮局到这9个村庄的总距离和最短。 A.(4.5,0)B.(4.5,4.5)C.(5,5)D.(5,0) 7.n个人拎着水桶在一个水龙头前面排队打水,水桶有大有小,水桶必须打满水, 水流恒定。如下说法不正确? A.让水桶大的人先打水,可以使得每个人排队时间之和最小 B.让水桶小的人先打水,可以使得每个人排队时间之和最小 C.让水桶小的人先打水,在某个确定的时间t内,可以让尽可能多的人打上水D.若要在尽可能短的时间内,n个人都打完水,按照什么顺序其实都一样 8.分治法的设计思想是将一个难以直接解决的大问题分割成规模较小的子问题, 分别解决子问题,最后将子问题的解组合起来形成原问题的解。这要求原问题和子问题。最接近点对问题实验报告
算法设计与分析:递归与分治法-实验报告
0007算法笔记——【分治法】最接近点对问题
2009.1算法设计与分析课程期末试卷-A卷(自测 )
分别用蛮力法、分治法、减治法实现a的N次方