计算机科学学院 王小明 ( 博士 / 教授 / 博士生导师 ) email: wangxm@snnu
DESCRIPTION
每节一经典 对大问题“ 分而治之,各个击破 ” :. 计算机科学学院 王小明 ( 博士 / 教授 / 博士生导师 ) Email: [email protected]. 分治法 : 把一个难于直接解决的大问题分解为若干个“相似”的小问题,再解所有小问题,然后把小问题的解“合并”,从而得到大问题的解 。 即:分治法是递归设计方法的一种具体策略 。 例如 :折半查找,快速排序,二叉树遍历,等等。. 第 4 讲 分治法. 分治法适用的条件 分治法所能解决的问题一般具有以下几个特征 : 该问题的规模缩小到一定的程度就可以容易地解决; - PowerPoint PPT PresentationTRANSCRIPT
分治法:把一个难于直接解决的大问题分解为若干个“相似”的小问题,再解所有小问题,然后把小问题的解“合并”,从而得到大问题的解。
即:分治法是递归设计方法的一种具体策略。
例如:折半查找,快速排序,二叉树遍历,等等。
第 4 讲 分治法
分治法适用的条件分治法所能解决的问题一般具有以下几个特征分治法所能解决的问题一般具有以下几个特征::• 该问题的规模缩小到一定的程度就可以容易地解决;• 该问题可以分解为若干个规模较小的相似问题;• 利用该问题分解出的子问题的解可以合并为该问题的
解;• 该问题所分解出的各个子问题是相互独立的,即子问
题之间不包含公共的子问题。
第 4 讲 分治法
第 4 讲 分治法
注意:如果各子问题是不独立的,则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然也可用分治法,但一般用动态规划较好。
适合用分治法 不适合用分治法
分治法设计框架 1 )分解:把原问题分解为多个规模较小、相 互独立、形式相同的子问题; 2 )解决:解决各个子问题(可能还需要分解); 3 )合并:将已得到的所有子问题的解合并为原问题 的解。注意:有些问题分解后,不必求所有子问题的解。例如:折半查找。在下列序列中找数字 2 : 1 , 2 , 3 , 4 , 5 , 6 , 7
第 4 讲 分治法
分治法算法框架
divide-and-conquer(P)
{if ( n<= n0) then {解子问题 ;
return( 子问题的解 ) } for (i=1,i<=k,i++)
{ 分解原问题为更小的子问题 Pi
yi=divide-and-conquer(Pi); // 递归的解各子问题 } T= merge(y1,...,yk) ;// 将子问题的解 yi 合并为原问题的解 return ( T ) }
第 4 讲 分治法
问题分解应注意的事项:
人们从大量实践中发现,在用分治法设计算法时,最好使子问题的规模大致相同。即将一个问题分成大小相等的 k 个子问题的处理方法是行之有效的。这种使子问题规模大致相等的做法是出自一种平衡 (balancing) 子问题的思想,它几乎总是比子问题规模不等的做法要好。
第 4 讲 分治法
分治法举例 例 13. 金块问题。
老板有 n 个金块,希望最优秀的雇员得到其中最重的一块,最差的雇员得到其中最轻的一块。假设有一台比较重量的仪器,如何用最少的比较次数找出最重和最轻的金块?
第 4 讲 分治法
理解金块问题:以 9 以内的实例理解问题。
第 4 讲 分治法
问题: 1. 最重的是那块?用 max 标记
2. 最轻的是那块?用 min 标记
算法策略:用蛮力法。即从第一块开始,查找哪块最重,哪块最轻。
第 4 讲 分治法
a[1] a[2] a[3] a[4] a[5]
1) max min2) <?
<?min
…
算法设计:Maxmin(float a[],int n)
{max=a[1];min=a[1];
for(i=2;i<=n;i=i+1)
{if(max<a[i])
max=a[i]
else if(min>a[i])
min=a[i]
}
Return(max, min)
}
第 4 讲 分治法
第 4 讲 分治法算法分析: (1) 时间复杂性和空间复杂性。
分析该算法可以看出,比较操作 max<a[i] 和 mix<a[i] 是执行频次最高的关键语句。因此以这两个语句执行的总次数作为该算法执行所需要的时间。最好情况下,金块由轻到重排列,不需要进行 min<a[i] 比较,而 max<a[i] 比较共需进行 n-
1 次 , 即可得到 max 和 min; 最坏情况下,金块由重到轻排列,还需要进行 n-1 次 min<a[i] 比较,才能得到最终的min ,因此共进行 2(n-1) 次比较。在平均情况下 ( 概率平均 ) , a[i] 将有一半的时间比 max 大,因此平均比较次数是3(n-1)/2 。所以算法时间复杂度为 O(n). 算法共用了 n 个存贮空间 (a[i]占用的空间),所以空间复杂度为 S(n).
第 4 讲 分治法算法正确性分析:
算法的正确性分析包含两方面的含义: 1 )算法是可终止的。 2 )算法是有效的。
在上述算法中,由于 n 是有限数,所以算法在有限次执行之后必然终止,这是显然的。
算法的有效性是指当算法正常终止时,最重、最轻的金块能够被找到 ( 没有遗漏现象 ) 。由于算法是从第一个金块开始逐一寻找,直到和第 n 个金块比较之后才结束,所以最后得到的必然是最重 (max) 、最轻 (min) 的金块 . 综合 1 )和 2 ),算法是正确的。
第 4 讲 分治法用分治法解决金块问题
典型二分法思想:一种简单的分治法。即当每次将比较大的一个问题一分为二,形成两个较小的问题,再把每个较小问题一分为二,变为更小的两个问题,…… , 直到得到容易解决的小问题为止,再解决所有小问题,然后把小问题的解逐层合并,得到原来大问题的解。
第 4 讲 分治法典型二分法示意图:
原问题
子问题 1 子问题 2
子问题 3子问题 4 子问题 5子问题 6
……
第 4 讲 分治法典型二分法用二叉树表示:
……
第 4 讲 分治法用二分法如何解决金块问题?
从两个简单实例谈起:
(1)假设只有一个金块,重 10克,则不需要比较轻重, 最重者和最轻者是同一个金块。即比较 0 次。
(2) 假设有 2 个金块,一个重 10克,另一个重 16
克,则 需要比较 1 次,可以把最重者和最轻者确定下来。(3) 当有多个金块时(假设 6 块),则用二分法对其
分 解,直到分解为( 1 )或( 2 )的情形时,问题很 容易解决。
第 4 讲 分治法假设 6 个金块重量如下 ( 以找最轻金块为例 ) :
2 6 4 3 8 1
一分为二(两组): 【 2 6 4 】 【 3 8 1 】
一分为二(四组): 【 2 6 】【 4 】 【 3 8 】【 1 】
解较小子问题: 2 4 3 1
合并子问题解: 2 1
lmin rmin
< ?
第 4 讲 分治法课堂练习:假设 6 个金块重量如下:找最重者
2 6 4 3 8 1
一分为二(两组): 【 2 6 4 】 【 3 8 1 】
一分为二(四组): 【 2 6 】【 4 】 【 3 8 】【 1 】
解较小子问题:
合并子问题解:
lmax rmax
< ?
第 4 讲 分治法用二分法解决金块问题算法设计:
问题抽象、简化为:在 n 个元素的集合中寻找最大和最小值元素。
(1) 将集合一分为二,变为两个集合,目的是在较小的两个集合中分别找最大、最小元素。
(2) 递归分解较小集合,直到每个集合中的元素个数≤ 2 ,然后找出小集合的最大、最小元素。
(3) 合并(回溯):自低向上把子问题的解合并,大元素中取最大者,小元素中取最小者,最后得到元问题的解。
第 4 讲 分治法用二分法解决金块问题算法描述:
Float a[n];
Maxmin(int I,int j,float &fmax,float &fmin)
{int mid;
float lmax,lmin,rmax,rmin;
if (i=j)
{fmax=a[i];fmin=a[i];}
i j
第 4 讲 分治法用二分法解决金块问题算法描述 ( 续 ) :
else if (i=j-1)
if ( a[i]<a[j] )
{fmax=a[j];fmin=a[i];}
else {fmax=a[j];fmin=a[i];}
else //i<>j-1
{mid=[(i+j)/2];//[x]表示取整数
maxmin(i,mid,lmax,lmin);
i j
i j
…
mid
第 4 讲 分治法用二分法解决金块问题算法描述 ( 续 ) :
maxmin(mid+1,j,rmax,rmin);
if (lmax>rmax)
fmax=lmax;
else
fmax=rmax; if (lmin>rmin) fmin=rmin; else fmin=lmin;}
}
解合并:
大者取大,
小者取小
第 4 讲 分治法用二分法解决金块问题算法分析:
以元素比较总次数作为 maxmin 算法的时间复杂度度量指标,用 T(n)表示比较总次数,则可以推导出递归关系:
T(n) 下界为
22)2/()2/(
21
10
)(
nnTnT
n
n
nT
22/3 n
第 4 讲 分治法对 T(n)推导:
22
3
)22(2
2)2/2(2
2)2/(2
248)2/(2
24)2)2/(2(4
24)2/(4
2)2)2/(2(2
2)2/(2)1)2/((2)(
1
1
1
11
1
1
11
33
3
2
2
n
T
nT
nT
nT
nT
nT
nTnTnT
kk
k
i
ikkk
k
i
ikk
kn 2
整理
整理
T(2)=1
整理
第 4 讲 分治法课外研究:
(1)学有余力的同学把金块问题递归算法改写为非递归算法,并分析算法的时间复杂性,然后和书上递归算法进行比较。
(2)学有余力的同学深入理解 p142” 算法分析 2” 。
(3)学有余力的同学设计程序,实现递归和非递归算法,上机实际测试运行时间上的差别。
第 4 讲 分治法小结:
( 1 )分治法的思想就是把大问题逐步分解为小问题……直到可解的小问题,最后把小问题的解逐层合并,得到大问题的解。
( 2 )二分法是最简单的分治法,每次把问题一分为二。
第 4 讲 分治法作业:
( 1 )预习 p143-145
(2) p189,习题 5 , 6 , 9
That’s all for today
See you next time
Good bye!