当前位置:文档之家› 第3章 分治法

第3章 分治法


时间复杂性分析: O(1) n 1 T (n) log3) T(n)=O(n 3 T ( n / 2 ) O ( n ) n 1 空间复杂性分析:S(n)=O(logn)
3.1 概述 – 引子(大整数的乘法)
如将大整数分成更多段,用更复杂的方式将其组合 起来,将有可能得到更优的算法。 最终的,这个思想导致了快速傅利叶变换 (Fast Fourier Transform, FFT) 的产生。该方法也可看作是 一个复杂的分治算法,对于大整数乘法,它也能在 O(nlogn) 时间内解决。
斗众如斗寡,形名是也。
旌旗曰形; 金鼓曰名 。
3.1 概述 – 分治策略
基于分治法解决问题:
首先将问题分解为k个子问题(最好规模相同)并分别 求解。如子问题规模仍不够小,则再划分为k个子问题。 如此递归进行,直到问题规模足够小易求解为止。 = n T(n)
n/2
T(n/4) T(n/4)
二分查找的伪代码(非递归):
BINARY-SEARCH-NOREC(A, n, x) while low <= high mid = (low + high) / 2 if x == A[mid] then return mid else if x > A[mid] then low = mid+1 else then high = mid-1 return -1
1 2 3 4 5 6 7 8 2 1 4 3 6 5 8 7 3 4 1 2 7 8 5 6 4 3 2 1 8 7 6 5 5 6 7 8 1 2 3 4 6 5 8 7 2 1 4 3 7 8 5 6 3 4 1 2 8 7 6 5 4 3 2 1
3.3 循环日程表 – 分治策略
如何分,即如何合理地进行问题的分解?
3.1 概述 – 引子(大整数的乘法)
问题陈述:
两个n位的大整数的乘法运算。
求解方法:
小学采用的方法:
一次性地乘:O(n2)
采用分治策略求解(二分):
每个迭代分解为4次相乘:O(n2) 每个迭代分解为3次相乘:O(nlog3) = O(n1.585)
X = Y =
a c
then return mid
else if x > A[mid] then return BINARY-SEARCH-REC(A, mid+1, high, x) else then return BINARY-SEARCH-REC(A, low, mid-1, x)
3.2 二分查找 – 伪代码
终止:
结束时low>high,待处理数组为空,表示x不在A中。每步的 部分数组中也不可能有x,因此x不存在于原数组,返回-1。
3.2 二分查找 – 算法分析
时间复杂性:
非递归:循环次数最大为logn,因此T(n)=O(logn)。
递归:
n 1 O(1) T (n) T (n / 2) O(1) n 1
输入为有序的序列。 取中间元素与待查找元素x进行比较,如果x等于中间 元素,则算法终止; 如x小于中间元素,则在序列的左半部继续查找。否则, 在序列的右半部继续查找。
重复利用了元素间的次序关系。
3.2 二分查找 – 伪代码
二分查找的伪代码(递归):
BINARY-SEARCH-REC(A, low, high, x) if low > high then return -1 mid = (low + high) / 2 if x == A[mid]
3.2 二分查找 – 求解步骤
二分查找的求解:
步骤1:确定合适的数据结构。设置数组s[n]来存放n个已 排好序的元素;变量low和high表示查找范围在数组中下 界和上界;middle表示查找范围的中间位置;x为特定元 素; 步骤2:初始化。令low=0;high=n-1; 步骤3:求中间位置。即middle=(low+high)/2; 步骤4:判定算法是否结束。判定low小于等于high是否 成立,如果成立,转步骤5。否则,算法结束; 步骤5:判断待查找元素与中间元素是否相等。如 x==s[mid],算法结束。如x>s[mid],令low=mid+1。 否则令high=mid-1,转步骤3。
一分为二
如何治,即如何进行问题的求解?
进行合并
问题的关键:
发现循环赛日程表制定过程中存在的规律性。
3.3 循环日程表 – 求解n=21
n=21个选手的比赛日程表的制定:
天数 编号 1 2 1 2 1
3.3 循环日程表 – 求解n=22
n=22个选手的比赛日程表的制定:
每个选手一天只能比赛一次; 循环赛一共需要进行n-1天。
需要注意的是:
由于n=2k,显然n为偶数。
3.3 循环日程表 – 分治策略
采用分治策略求解的分析:
将所有的选手分为两半,n个选手的比赛日程表就可通过 为n/2个选手设计的比赛日程表来决定。递归进行分割, 直到只剩下2个选手时,比赛日程表的制定就变得很简单。
3.2 二分查找 – 求解示例
如在如下序列中查找元素x=12:
0 6 1 12 2 15 3 18 4 22 5 6 7 35 8 46 9 58 10 60 25 28
(1)
low=0
middle=5
high=10
0 6
1 12
2 15
3 18
4 22
5
6
7 35
8 46
9 58
10 60
25 28
子问题的合并
天数 编号 1 2 3 4 5 6 7 8 1 2 1 4 3 6 5 8 7 2 3 4 1 2 7 8 5 6 3 4 3 2 1 8 7 6 5
3.3 循环日程表 – 求解n=23
n=23个选手的比赛日程表:
天数 编号 1 2 3 4 5 6 7 8 1 2 1 4 3 6 5 8 7 2 3 4 1 2 7 8 5 6 3 4 3 2 1 8 7 6 5 4 5 6 7 8 1 2 3 4 5 6 5 8 7 2 1 4 3 6 7 8 5 6 3 4 1 2 7 8 7 6 5 4 3 2 1
保持:
每次循环前,x存在于A[low..high]中。对于A[mid]<x, A[low..mid]均小于x,x只可能存在于A[mid+1..high]中; 对于A[mid]>x, A[mid..high]均大于x,x只可能存在于 A[low, mid-1]中;对于A[mid]==x,直接返回x对应下标。
子问题的比赛日程表
天数 编号 1 2 3 4 1 2 1 4 3
22个选手的比赛日程表
天数 编号 1 2 3 4 1 2 1 4 3 2 3 4 1 2 3 4 3 2 1
3.3 循环日程表 – 求解n=23
n=23个选手的比赛日程表的制定:
子问题的比赛日程表
天数 编号 1 2 3 4 5 6 7 8 1 2 1 4 3 6 5 8 7
第3章 分治法
聂艳明 信息工程学院
第3章 分治法
3.1 3.2 3.3 3.4 3.5 3.6 概述 二分查找 循环日程表 棋盘覆盖问题 合并排序 快速排序
本章的要点和难点
要点:
分治法的基本思想、基本要素与求解步骤; 分治法的应用。
难点:
分治法的最优子结构性质。
最好是使子问题的规模大致相同。
3.1 概述 – 分治法的复杂性分析
分治法求解问题的时间复杂性分析:
将规模为n的问题DIVIDE成k个规模为n/m的子问题去 解。设分解阈值n0=1,且CONQUER解规模为1的问题 耗费1个单位时间。再设将原问题分解为k个子问题及用 COMBINE将k个子问题的解合并为原问题的解需用f(n) 个单位时间。则有: ì O(1) n= 1
分治法的基本步骤:
DIVIDE-AND-CONQUER(P)
if(|P| <= n0) //问题规模足够小,n0为规模阈值 then CONQURE(P); //解决小问题 subs = DIVIDE(P) //分解为子问题,subs为子问题集 for i = 1 to subs.length() r[i]=DIVIDE-AND-CONQUER(subs[i]); //递归求解子问题 return COMBINE(r); //将各子问题的解合并为原问题的解
T(n)=O(n2)

空间复杂性分析:S(n)=O(logn)
3.1 概述 – 引子(大整数的乘法)
分治法(二分):
每个迭代分解为3次相乘: XY = ac 2n + ((a-b)(d-c)+ac+bd) 2n/2 + bd XY = ac 2n + ((a+b)(d+c)-ac-bd) 2n/2 + bd 或
基于后向导入或递归树可知:T(n)=O(logn) 。
空间复杂性:
非递归:O(1)。 递归:O(logn)。
3.3 循环日程表 – 问题描述
问题描述:
设有n=2k个运动员要进行羽毛球循环赛,现要设计一个 满足以下要求的比赛日程表:
每个选手必须与其它n-1个选手各赛一次;
(2)
Hale Waihona Puke low=0middle=2 high=4
3.2 二分查找 – 求解示例
如在如下序列中查找元素x=12:
0 6 1 12 2 15 3 18 4 22 5 6 7 35 8 46 9 58 10 60 25 28
(3)
low=0 high=1 middle=0
相关主题