分治算法Divide-and-Conquer概述

设计过程分为三个阶段

Divide: 整个问题划分为多个子问题  T(n)=D(n)

Conquer:求解各子问题(递归调用正设计的算法)  T(n)=aT(n/b)

Combine:合并子问题的解, 形成原始问题的解T(n)=C(n)

Note: 将规模为n的问题划分为a个子问题,每个问题的大小为n/b。(b可能不等于a!)

时间复杂度:T(n)=θ(1)     if n<c常数

T(n)=aT(n/b)+D(n)+C(n)

经典问题1:归并排序

Divide阶段:在中间节点节段 时间为O(1)

Conquer阶段:两个子问题每个问题规模为n/2因此T(n)=2T(n/2)

Combine阶段:依次比对 O(n)

所以时间复杂度为 T(n)=2T(n/2)+O(n)   Master方法计算(第2种情况)T(n)=(nlogn)

 

经典问题2:大整数乘法

输入:n位二进制整数XY            
输出:XY的乘积

分治思想:

X = A<<n/2+B  Y= C<<n/2 + D 即将大数划分为两个子部分

X*Y = (A<<n/2+B)*(C<<n/2+ D) = (A*C)<<n + (A*D+B*C)<<n/2 +C*D

将XY问题划分为计算AC,BD,AD,BC四个子问题,每个问题规模为n/2  (!!a不等于b)

T(n)=4T(n/2)+θ(n)  Master方法计算  Master方法计算(第一种情况)T(n)=(n^2)

优化:

(A-B)*(C-D) = AC+BD-(BC+AD) 所以XY的等式中(A*D+B*C)就可以用AC+BD+(B-A)(C-D)代替。

即,把原来计算AC,BD,AD,BC四个子问题,转换为AC、BD、CD三个子问题。

T(n)=3T(n/2)+θ(n)  计算的T(n)=O(n^(log2^3))≈O(n^(1.59))

经典问题3:矩阵乘法

输入:两个矩阵A、B           输出:A*B

分治:

一般思路就是划分了8个,规模为n/2的子问题。所以T(n)=8T(n/2)+θ(n)

可是减少子问题个数是优化的好的方向。之后就有善于思考的人提出用7个子问题实现:

M1 = A11 (B12 - B22)

M2 = (A11 + A12) B22

M3 = (A21 + A22) B11

M4 = A22 (B21 - B11)

M5 = (A11 + A22) (B11 + B22)

M6 = (A12 - A22) (B21 + B22)

M7= (A11 - A12) (B11 + B12)

C11 = M5 + M4 - M2 + M6

C12 = M1 + M2

C21 = M3 + M4

C22 = M5 + M1 – M3 – M7

之后就成功的降低时间复杂度。T(n)=7T(n/2)+θ(n)=O(n^(log2^7 ))≈O(n^(2.81))

上文说的经典分治算法,基本以减少子问题个数来降低时间复杂度,在划分和合并阶段没有特别的处理。

接下来的几章主要看比较有意思的三个问题。

时间: 2024-11-13 09:39:45

分治算法Divide-and-Conquer概述的相关文章

分治算法(Divide and Conquer)

分治算法 在计算机科学中,分治法是建基于多项分支递归的一种很重要的算法范式.字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并. 分治法所能解决的问题一般具有以下几个特征: 问题的规模缩小到一定的程度就可以容易地解决 问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质 利用该问题分解出的子问题的解可以合并为该问题的解 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问

分治算法——Karastsuba算法

分治(Divide and Conquer)算法:问题可以分解为子问题,每个问题是可以独立的解决的,从子问题的解可以构建原问题. Divide:中间分.随机分.奇偶分等,将问题分解成独立的子问题 Conquer:子问题的解可以单独解决,从子问题的解构建原问题最终的解 Combine:每一步将子问题产生的解进行合并得到最终的解,合并的复杂度影响最终的算法时间复杂度 Karatsuba算法是在普通乘法算法的基础上进行的提升,使得最终的复杂度从O(n^2)变为了O(n^1.585),基本思想是将原问题

分治算法学习 Divide and Conquer

分治思想: 分治算法的思想就是 对于某些特定种类的问题  如果问题的规模很小,那么就直接解决,如果问题的规模比较大,那么就把问题先分解为规模小的但是问题相同的子问题 ,并且不断分解直到规模足够小,再递归地解决这些问题 如果原问题可分割成k个子问题,1<k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的. 递归与分治经常是一起使用的 能够用分治的情况 : 1.问题复杂性随规模减小而减小 2.问题具有最优子结构性质        最优子结构:如果问题的最优解所包

【算法】2 由股票收益问题再看分治算法和递归式

回顾分治算法 分治算法的英文名叫做"divide and conquer",它的意思是将一块领土分解为若干块小部分,然后一块块的占领征服,让它们彼此异化.这就是英国人的军事策略,但我们今天要看的是算法. 如前所述,分治算法有3步,在上一篇中已有介绍,它们对应的英文名分别是:divide.conquer.combine. 接下来我们通过多个小算法来深化对分治算法的理解. 二分查找算法 问题描述:在已排序的数组A中查找是否存在数字n. 1)分:取得数组A中的中间数,并将其与n比较 2)治:

lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法

本文属作者原创,转载请注明出处 http://www.cnblogs.com/qxred/p/dcalgorithm.html 本系列目录: lanczos算法及C++实现(一)框架及简单实现 lanczos算法及C++实现(二)实对称阵奇异值分解的QR算法 lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法 0. 参考文献 https://en.wikipedia.org/wiki/Divide-and-conquer_eigenvalue_algorithm A. Mel

分治算法例子集锦

描述: 两部分组成 分(divide):递归解决较小的问题 治(conquer):然后从子问题的解构建原问题的解 三个步骤 1.分解(Divide):将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题: 2.解决(Conquer):若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题: 3.合并(Combine):将各个子问题的解合并为原问题的解. 四个适用条件 1.该问题的规模缩小到一定的程度就可以容易地解决: 2.该问题可以分解为若干个规模较小的相同问题,即该问题具有最

普林斯顿公开课 算法2-1:排序概述

目标 对所有类型的数据进行排序. 问题 排序函数如何知道比较的是哪种类型的数据呢? 回调函数 这时候就需要引入回调函数的概念了.回调函数就是将可执行的代码作为参数进行传递. 实现回调的方法 在Java中可以通过接口来实现,在C语言中可以通过函数指针来实现,C++中可以通过class-type functor,也就是重载操作符operator ()的类,在C#中可以使用Delegate委托,在Python/Perl/ML/javascript中可以直接传递函数. JDK中提供了Comparable

分治算法

分治算法即将一个问题划分成多个子问题求解,最后的结果就是几个子问题的合集,通常图形类的算法,尤其是2的几次方数组问题可以优先考虑. 汉诺塔和二分搜索都是分治算法的思想,个人觉得最好体现分治算法的demo是棋盘覆盖问题,代码如下: #include <stdio.h> #include <stdlib.h> #define SIZE 4 static int title = 1; //title表示L型骨牌的编号 static int board[SIZE][SIZE]; /** *

自我练习 - 分治算法

2017-08-21 19:38:32 writer:pprp /* theme:第一章 - 分治算法 name:魔法石的诱惑 writer:pprp description:给你Q(0<=Q<=10^8),问你最小的自然数N使N的阶乘在十进制下包含Q个0 input:Q output: N date:Monday 2017/8/21 */ #include <bits/stdc++.h> using namespace std; const int maxn = 50000000