第2章 递归与分治策略-2(1)
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
8
算法设计与分析 > 递归与分治>寻找最大与最小元素
• 递归方程 • T(n)= 0 1 T(└ n /2┘)+T(┌ n/2┐)+2 n=1 n=2 n>2
• T(n)= ┌ 3n/2 – 2 ┐
比较次数优于方法一。
9
算法设计与分析 > 递归与分治>大整数的乘法
2.4 大整数的乘法
问题: 设X,Y是两个n位二进制数,求XY.
11
算法设计与分析 > 递归与分治>大整数的乘法
XY=(A 2n/2 +B) (C 2n/2 +D) =AC2n+(AD+CB)2n/2 +BD 计算XY须4次n/2位整数的乘法,3次不超过2n位的整数加法, 没有改善 2次移位(乘2n 和乘2n/2 ).XY的 T(n)满足
T(1)= O(1) T(n)= Tቤተ መጻሕፍቲ ባይዱn)= 4T(n/2)+ O(n)
2
算法设计与分析 > 递归与分治
如何分解?
大量实践中发现,在用分治法设计算法时,最好 使子问题的规模大致相同。这种使子问题规模大
致相等的做法是出自一种平衡(balancing)子问
题的思想,它几乎总是比子问题规模不等的做法 要好。 子问题规模大致相同、平衡,这样最有效。通常 k=2.
3
算法设计与分析 > 递归与分治
算法设计与分析 > 递归与分治>大整数的乘法
{X,Y为2个小于2n的二进制整数,返回结果为X和Y的乘积XY} { S=SIGN(X)*SIGN(Y); 存放XY的符号 X:=ABS(X);Y:=ABS(Y); if n=l then if (X=1) and (Y=1) then return(S) else return(0) else { A:=X的左边n/2位; B:=X的右边n/2位; C:=Y的左边n/2位; D:=Y的右边n/2位; m1:=MULT(A,C,n/2); m2:=MULT(A-B,D-C,n/2); 存放三个乘积 m3:=MULT(B,D,n/2); S:=S*(m1*2n+(m1+m2+m3)*2n/2+m3); return (S) }} 二进制大整数乘法同样可应用于十进制大整数的乘法
m m
j 0
适用问题
大数相乘,矩阵乘法,快速富立叶变换, 棋盘覆盖,排序,选择 等.
5
算法设计与分析 > 递归与分治>二分查找
例 题 1-1
已知不重复且从小到大排列的m个整数的数组 A[1...m],m=2K,K为正整数.对于给定的整数c,要求找到 一个下标i,使得A[i]=c.找不到返回0. 算法1-1:顺序查找
解得 T(n) =O(n2)
改进:
XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD
计算XY须3次n/2位整数的乘法,6次加.减和2次移位 T(1)= O(1) T(n)= 解得 T(n) =O(nlog3) T(n)= 3T(n/2)+ O(n)
如果将大整数分成更多段,用更复杂的方式把它们组合起来, 将有可能得到更优的算法。 最终的,这个思想导致了快速傅利叶变换(Fast Fourier 12 Transform)的产生。该方法也可以看作是一个复杂的分治算法。
function search(c) { i:=1; while A[i]<c and i<m do i:=i+1; if A[i]=c then search:=i; else search:=0; }
最好情况Tmin (m)=4, Tmin (m)=O(1) 最坏情况Tmax(m) =3+5m, Tmax(m) =O(m)
分治算法:划分A,B为四个n/2(n=2K )阶方阵,则:
A 11 A 12 B 11 B 12 C 11 C 12 C A 21 A 22 B 21 B 22 C 21 C 22
C11=A11B11+A12B21 C12=A11B11+A12B21 C21=A11B11+A12B21 C22=A11B11+A12B21 若 n=2,可直接计算C; 若n>2,C需8个n/2阶方阵的乘法和4个加法. T(2)= O(1) T(n)= 8T(n/2)+O(n2) 得: T(n)=O(n3)
13
大数相乘的分治递归算法 function MULT(X,Y,n)
算法
算法设计与分析 > 递归与分治>矩阵相乘的Strassen法
2.5 矩阵相乘的Strassen法
常规算法:设矩阵 A = (aij)nn , B = (bij)nn , C=AB=(cij)nn
c i , j a i,k bk , j
分而治之,递归求解(或迭代求解)
1
算法设计与分析 > 递归与分治
分治策略的适用条件
① 可分解性:复杂性随问题规模的减少而减少; ② 递归性:子问题具有相同的模式,因而可以用
递归方法处理;
③ 可归并性:子问题的解不是原问题的解时必须 能把子问题的解归并成原问题的解; ④ 独立性:子问题相互独立,没有交叉、重复。
C:=
M5 M4 M 2 M6 M1 M 2 M 3 M4 M 5 M1 M 3 M 7
17
算法设计与分析 > 递归与分治>矩阵相乘的Strassen法
分析:
T(n)=
T(2)= O(1) T(n)= 7T(n/2)+18(n/2)2
算法设计与分析 > 递归与分治>矩阵相乘的Strassen法
算法
矩阵相乘Strassen算法
procedure STRASSEN(n,A,B,C); { if n=2 then MATRIX_MULTIPLY(A,B,C) else { 将矩阵A和B分块; STRASSEN( n/2,A11,B12-B22,M1); STRASSEN( h/2,A11+A12,B22,M2); STRASSEN( n/2,A21+A22,B11,M3); STRASSEN( n/2,A22,B21-B11,M4); STRASSEN( n/2,A11+A22,B11+B22,M5) STRASSEN( n/2,A12-A22,B21+B22,M6); STRASSEN( n/2,A11+A21,B11+B12,M7)
例 题 1-1
最坏情况Tmax(m) =O(logm)
7
算法设计与分析 > 递归与分治>寻找最大与最小元素
寻找最大与最小元素
• 从无序的数组a[0:n-1]中寻找最大与最小元素 • 方法一: 找最大元素:n-1次比较 找最小元素:n-2次比较 总计:2n-3次比较 • 方法二(分治法) 左右两部分分别求max1,min1和max2,min2 合成:fmax=max(max1,max2) fmin =min(min1,min2)
算法设计与分析 > 递归与分治
2.2 基本思想 分治法所能解决的问题一般具有以下特征: 该问题可以分解为若干个规模较小的相同问题; 该问题所分解出的各个子问题是相互独立的,即子 问题之间不包含公共的子问题; 该问题的规模缩小到一定程度就可以容易地解决; 利用该问题分解出的子问题的解可以合并为该问题 的解。
1 (3+2)m
1+1
6
算法设计与分析 > 递归与分治>二分查找
算法1-2:二分查找 function b-search(c) { L:=1; U:=m; found:=false; while not found and U>=L do { i:=(L+U)div2; if c=A[i] then found:=true else if c>A[i] then L:=i+1 else U:=i-1 } if found then b-search:=1 else b-search:=0 }
设问题P(n)分解成k个规模为n/m的子问题,阀值n0=1,求解P(1)的 时间耗费为O(1).将P(n)分解及合并成P(n)的解的时间为f(n),则 分治法解规模为n的问题的最坏时间复杂性函数T(n)满足:
log n 1 T(1)=O(1) 解得: log k T(n)= T(n) n k j f(n/m j ) T(n)=kT(n/m)+f(n)
4
算法设计与分析 > 递归与分治
算法的时间复杂性
Divide-and-Conquer(P) if ( |P|<=n0) Adhoc(P); divide P into smaller subinstances P1 ,P2,... ,Pk; for (i = 1;i <= k; i++) yi=Divide-and-Conquer(Pi); return Merge( yl ,..., yk); O(1) f(n) kT(n/m)
10
算法设计与分析 > 递归与分治>大整数的乘法
如何设计两个大整数的乘法运算的有效的算法? 要求:大整数超出long int表示范围,而浮点表示不精确。 假设:乘法时间远大于加减法、移位运算 将两个一位数的乘法或加法看作一步运算,那么,两个N位 数X*Y相乘,需要O(N2)时间
分治算法思路:若两个1位数相乘或相加看作1步运算,按传统 乘法需O(n2)次运算.将每个n(n=2K)位的二进制整数分为2段, 每段的长为n/2位 X=A 2n/2 +B Y= C 2n/2 +D。
K 1
n
计算C共需nn2个乘法,n2(n-1)个加法. T(n)=O(n3) 求出矩阵C的n2个元素所需的时间为0(n3)。 分治法 1969年,Strassen采用了类似于在大整数乘法中用过的分 治技术,将计算2个n阶矩阵乘积所需的计算时间改进到 O(nlog7)=O(n2.81)。
14
算法设计与分析 > 递归与分治>矩阵相乘的Strassen法
算法
通常,在分析算法的复杂性时,加法和乘法当作基本运 算,即执行一次加法或乘法运算所需的计算时间当作一个 仅取决于计算机硬件处理速度的常数。 这个假定仅在硬件能对整数直接表示和处理时才合理 。然而,在处理很大整数时,硬件无法直接表示和处理。 而用浮点数来表示则只能近似值,计算结果中的有效数字 也受到限制。若要精确地表示大整数并在计算结果中要求 精确地得到所有位数上的数字,必须用软件方法来实现大 整数的算术运算。
将规模为N的问题分解为k个规模较小的子问题,使这些子问题相互 独立可分别求解,再将k个子问题的解合并成原问题的解.如子问题 的规模仍很大,则反复分解直到问题小到可直接求解为止. 在分治法中,子问题的解法通常与原问题相同,自然导致递归过程. 应用当中,通常将问题分解为k个(k=2)大小相等的子问题. 算法一般模式 阀值 Divide-and-Conquer(P) if ( |P|<=n0) Adhoc(P); 直接求解问题p 问 divide P into smaller subinstances P1 ,P2,... ,Pk; 题 for (i = 1;i <= k; i++) 的 规 yi=Divide-and-Conquer(Pi); 模 return Merge( yl ,..., yk); 将p1,p2,…pk的解y1,y2,…yk 合并成p的解
T(n)=
15
算法设计与分析 > 递归与分治>矩阵相乘的Strassen法
改进 M1=A11 (B12-B21)
M6= (A12+A22)(B21+B22) M7 = (A11 - A21)(B11+B12) M2= (A11+A12) B22 M3= (A21+A22) B11 C11 =M5+ M4 - M2+M6 C12 = M1+M2 M4= A22 (B21-B11) C21 = M3+M4 M5= (A11+A22)(B11+B22) C22 = M5+M1 - M3 - M7 验证:C22 = M5+M1-M3-M7 = (A11+A22)(B11+B22) +A11 (B12-B21) -(A21+A22) B11 - (A11-A21)(B11+B12) =A11B11+A11B22+A22B11+A22B22+A11B12 -A11B22- A21B11 - A22B11 - A11B11 - A11B12+A21B11+A21B12 =A21B12+A22B22