分治算法详解ppt课件
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
12
合并排序
最坏时间复杂度:O(nlogn) 平均时间复杂度:O(nlogn) 辅助空间:O(n)
13
棋盘覆盖
在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其它方格不 同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋 盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的 特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不 得重叠覆盖。
} return -1; }
时间,因此整个算法在最坏情况下 的计算时间复杂性为O(logn) 。
9
分治法求数组最大值
给定n个元素a[0:n-1],现要在这n个元素中找出最大值x。 思路: 将数组一分为二 求前半部分的最大值位置,求后半部分最大值位置(分的过 程) 求前后两部分最大值位置。(合的过程)
board[tr + s][tc + s] = t;
else {// 此棋盘中无特殊方格
// 覆盖其余方格
// 用 t 号L型骨牌覆盖左下角
chessBoard(tr+s, tc+s, tr+s, tc+s, s)1;8}
}
循环赛日程表
设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次; (2)每个选手一天只能赛一次; (3)循环赛一共进行n-1天。
分分治割T法成(n的一) 设 些计 规思 模想 较是小=,的将相一同n个问难题以,直以接便解 各决 个的 击大 破问 ,题,
分而治之。
n/2
n/2
n/2
n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/54)T(n/4
// 覆盖右上角子棋盘
// 特殊方格在此棋盘中源自if (dr < tr + s && dc >= tc + s)
chessBoard(tr+s, tc+s, dr, dc, s);
// 特殊方格在此棋盘中
else {// 用 t 号L型骨牌覆盖左上角
chessBoard(tr, tc+s, dr, dc, s);
T(n)
=n
n/m
n/m
n/m n/m
T(n/mT2)(n/mT2)(n/mT2)(n/m2) T(n/mT2)(n/mT2)(n/mT2)(n/m2)T(n/mT2)(n/mT2)(n/mT2)(n/m2T) (n/mT2)(n/mT2)(n/m3 T2)(n/m
算法总体思想
将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
14
棋盘覆盖
当k>0时,将2k×2k棋盘分割为4个2k-1×2k-1 子棋盘(a)所示。 特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特 殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可 以用一个L型骨牌覆盖这3个较小棋盘的会合处,如 (b)所示,从 而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这 种分割,直至棋盘简化为棋盘1×1。
return merge(y1,...,yk); //将各子问题的解合并为原问题的解
} 人们从大量实践中发现,在用分治法设计算法时,
最好使子问题的规模大致相同。即将一个问题分成
大小相等的k个子问题的处理方法是行之有效的。
这种使子问题规模大致相等的做法是出自一种平衡
(balancing)子问题的思想,它几乎总是比子问题
分治
1
算法总体思想
对这k个子问题分别求解。如果子问题的规模仍然不够 • 将小要,求则解再的划较分大为规k个模子的问问题题,分如割此成递k归个的更进小行规下模去的,子直问
题到。问题规模足够小,很容易求出其解为止。
T(n)
=n
T(n/m)
T(n/m)
T(n/m)
T(n/m)
2
算法总体思想
对将这求出k个的子小问规题模分的别问求题解的。解如合果并子为问一题个的更规大模规仍模然的不问够 小题,的则解再,划自分底为向上k个逐子步问求题出,原如来此问递题归的的解进。行下去,直 到问题规模足够小,很容易求出其解为止。
{ if (left<right) {//至少有2个元素 int i=(left+right)/2; //取中点 mergeSort(a, left, i); mergeSort(a, i+1, right); merge(a, b, left, i, right); //合并到数组b copy(a, b, left, right); //复制回数组a }
15
棋盘的识别
首先,子棋盘的规模是一个必要的信息,有了这个 信息,只要知道左上角的方格在原棋盘中的行、列 号就可以标识这个子棋盘了;其次子棋盘中残缺方 格或“伪”残缺方格直接用它们在原棋盘中的行、 列号标识。 ①tr表示棋盘左上角方格的行号; ②tc表示棋盘左 上角方格的列号 ③dr表示特殊方格所在的行号 ④dc 表示特殊方格所在的列号, ⑤size表示方形棋盘行 数或列数。
T(n)
=n
n/m
n/m
n/m n/m
T(n/mT2)(n/mT2)(n/mT2)(n/m2) T(n/mT2)(n/mT2)(n/mT2)(n/m2)T(n/mT2)(n/mT2)(n/mT2)(n/m2T) (n/mT2)(n/mT2)(n/m4 T2)(n/m
算法总体思想
将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
分治法的适用条件
分治法所能解决的问题一般具有以下几个特征: • 该问题的规模缩小到一定的程度就可以容易地解决; • 该问题可以分解为若干个规模较小的相同问题,即该
问题具有最优子结构性质 • 利用该问题分解出的子问题的解可以合并为该问题的
解; 这•条该特问征题涉所及分到解分出治的法各的个效子率问,题如是果相各互子独问立题的是,不即子问 独立题的之,间则不分包治含法公要共做的许子多问不题必。要的工作,重复地 解用公动共态因而这可能如可的规为 增 条 以 否 果 以子划问加特满利具考问较题,征足用备虑题好贪的因是的分了,。计此应,治前心此算大用此法两算时复部分特完条法虽杂分治征全特或然性问法反取征动也一题的映决,态可般满前了于而规用是足提递问不划分随这,归题具。治着个它思是备法问特也想否第,题征是的具三但规。大应有条一模多用这特般的数条征增问特,加题征则,
6
分治法的基本步骤
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); //递归的解各子问题
}
11
合并排序
算法mergeSort的递归过程可以消去。 初始序列 [49] [38] [65] [97] [76] [13] [27]
第一步 第二步
[38 49] [65 97] [13 76] [27]
[38 49 65 97]
[13 27 76]
第三步
[13 27 38 49 65 76 97]
int特殊方格在此棋盘中chessboardtrtcdrdc号l型骨牌覆盖右下角boardtr覆盖其余方格chessboardtrtctrs1tcs1特殊方格在此棋盘中chessboardtrtcsdrdc号l型骨牌覆盖左下角boardtr覆盖其余方格chessboardtrtcstrs1tcs特殊方格在此棋盘中chessboardtrstcdrdc号l型骨牌覆盖右上角boardtr覆盖其余方格chessboardtrstctrstcs1特殊方格在此棋盘中chessboardtrstcsdrdc号l型骨牌覆盖左上角boardtr覆盖其余方格chessboardtrstcstrstcs18循环赛日程表循环赛日程表设计一个满足以下要求的比赛日程表
board[tr + s - 1][tc + s - 1] = t;
chessBoard(tr+s, tc, tr+s, tc+s-1, s);}
// 覆盖其余方格
// 覆盖右下角子棋盘
chessBoard(tr, tc, tr+s-1, tc+s-1, s);} if (dr >= tr + s && dc >= tc + s)
每执行一次算法的while循环, 待
int m = (l+r)/2;
搜索数组的大小减少一半。因此,
if (x == a[m]) return m;
在最坏情况下,while循环被执行了
if (x < a[m]) r = m-1; else l = m+1; O(logn) 次。循环体内运算需要O(1)
按分治策略,将所有的选手分为两半,n个选手的比赛日程表
就可以通过为n/2个选手设计的比赛日程表来决定。递归地用
对选手进行分割,直到只剩下2个选手时,比赛日程表的制定
就变得很简单。这时只要让这2个选手进行比赛就可以了。
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
else {// 此棋盘中无特殊方格
4T
(k
O/c/(h特1e)s殊sB方o格ar在d(此tkr+棋s,盘t0c中, dr, dc, s); elbs1eo)a{r/d/ [用Otr +(t1号s)][Ltc型k+骨s牌-0覆1] 盖= t右; 上角
// 用 t 号L型骨牌覆盖T(右n下)=角O(4k) 渐进意// 覆义盖下其的余方最格优算法
10
合并排序
基本思想:将待排序元素分成大小大致相同的2个子集合,分 别要对求2的个排子好集序合的进集复行合杂排。度序分,析最T (终n)将 排2好T (序n /O的2()1子) O集(n合) 合nn 并 11成为所 void MergeSort(Type a[], int lTef(t,nin)=t rOigh(nt)logn) 渐进意义下的最优算法
规模不等的做法要好。
7
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。 分析: 该问题的规模缩小到一定的程度就可以容易地解决;
该问题可以分解为若干个规模较小的相同问题;
分解出的子问题的解可以合并为原问题的解; 分析:分比解较出x和的a各的个中子间问元题素是a[相mi互d]独,立若的x=。a[mid],则x在L中的 位置就是mid;如果x<a[mid],由于a是递增排序的,因此假 分可用如a的分面用[m析以条x后析或条在id:确件面:后件]a的定查面。如很中前找查果x显的是面找然nx话否即=查此x,1在可是即找问x表。独必只x题即中无立然有分可。论的排一解;因是子在个出如此在问a元的[果m这前题素子ixd个面,,>]问的a问还因则[题i前]题是此,只相面满后满同要互,足面足理比独所分查分我较立以治找治们这,我法法x只个,即们的的要元其在只第第在素方a要一四[a和i法][在的m个个x都就i前适适d] 和在a中查找x一样,只不过是查找的规模缩小了。这就说明 了此问题满足分治法的第二个和第三个适用条件。
16
棋盘数据结构
• 用二维数组Board[][]来模拟棋盘,Board[1][1]是棋盘的左上角方格。 title表示L 型骨牌的编号,其初始值为0。覆盖残缺棋盘所需要的三格 板数目为:(size*size -1)/3。将这些 三格板编号为1到(size*size-1)/3, 则将覆盖残缺棋盘的三格板编号存储在数组Board的对应位置,这样 输出数组内容就是问题的解。如果是一个4 ×4的棋盘,特殊方格为 (2,1),那么程序的输出为对于如图8-6(a)所示的棋盘,其结果为8-6(b) 所示的棋盘。其中特殊方格为0,相同数字的为同一骨牌。
17
棋盘覆盖
void chessBoard(int tr, int tc, int dr, int dc, int size)
{
board[tr + s - 1][tc + s] = t;
if (size == 1) return;
// 覆盖其余方格
int t = tile++, // L型骨牌号
chessBoard(tr, tc+s, tr+s-1, tc+s, s);}
s = size/2; // 分割棋盘
// 覆盖左下角子棋盘
// 覆盖左上角子棋盘
if (dr >= tr + s && dc < tc + s)
if (dr < tr +复s &杂& 度dc 分< tc析+ s)
/c/h特es殊sB方o格ar在d(此tr,棋tc盘, d中Tr, d(ck,)s);
8
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。
据此容易设计出二分搜索算法:
template<class Type>
int BinarySearch(Type a[], const Type& 算x, in法t l,复int杂r) 度分析:
{ while (r >= l){
合并排序
最坏时间复杂度:O(nlogn) 平均时间复杂度:O(nlogn) 辅助空间:O(n)
13
棋盘覆盖
在一个2k×2k 个方格组成的棋盘中,恰有一个方格与其它方格不 同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋 盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的 特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不 得重叠覆盖。
} return -1; }
时间,因此整个算法在最坏情况下 的计算时间复杂性为O(logn) 。
9
分治法求数组最大值
给定n个元素a[0:n-1],现要在这n个元素中找出最大值x。 思路: 将数组一分为二 求前半部分的最大值位置,求后半部分最大值位置(分的过 程) 求前后两部分最大值位置。(合的过程)
board[tr + s][tc + s] = t;
else {// 此棋盘中无特殊方格
// 覆盖其余方格
// 用 t 号L型骨牌覆盖左下角
chessBoard(tr+s, tc+s, tr+s, tc+s, s)1;8}
}
循环赛日程表
设计一个满足以下要求的比赛日程表: (1)每个选手必须与其他n-1个选手各赛一次; (2)每个选手一天只能赛一次; (3)循环赛一共进行n-1天。
分分治割T法成(n的一) 设 些计 规思 模想 较是小=,的将相一同n个问难题以,直以接便解 各决 个的 击大 破问 ,题,
分而治之。
n/2
n/2
n/2
n/2
T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/4)T(n/4) T(n/4)T(n/4)T(n/54)T(n/4
// 覆盖右上角子棋盘
// 特殊方格在此棋盘中源自if (dr < tr + s && dc >= tc + s)
chessBoard(tr+s, tc+s, dr, dc, s);
// 特殊方格在此棋盘中
else {// 用 t 号L型骨牌覆盖左上角
chessBoard(tr, tc+s, dr, dc, s);
T(n)
=n
n/m
n/m
n/m n/m
T(n/mT2)(n/mT2)(n/mT2)(n/m2) T(n/mT2)(n/mT2)(n/mT2)(n/m2)T(n/mT2)(n/mT2)(n/mT2)(n/m2T) (n/mT2)(n/mT2)(n/m3 T2)(n/m
算法总体思想
将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
14
棋盘覆盖
当k>0时,将2k×2k棋盘分割为4个2k-1×2k-1 子棋盘(a)所示。 特殊方格必位于4个较小子棋盘之一中,其余3个子棋盘中无特 殊方格。为了将这3个无特殊方格的子棋盘转化为特殊棋盘,可 以用一个L型骨牌覆盖这3个较小棋盘的会合处,如 (b)所示,从 而将原问题转化为4个较小规模的棋盘覆盖问题。递归地使用这 种分割,直至棋盘简化为棋盘1×1。
return merge(y1,...,yk); //将各子问题的解合并为原问题的解
} 人们从大量实践中发现,在用分治法设计算法时,
最好使子问题的规模大致相同。即将一个问题分成
大小相等的k个子问题的处理方法是行之有效的。
这种使子问题规模大致相等的做法是出自一种平衡
(balancing)子问题的思想,它几乎总是比子问题
分治
1
算法总体思想
对这k个子问题分别求解。如果子问题的规模仍然不够 • 将小要,求则解再的划较分大为规k个模子的问问题题,分如割此成递k归个的更进小行规下模去的,子直问
题到。问题规模足够小,很容易求出其解为止。
T(n)
=n
T(n/m)
T(n/m)
T(n/m)
T(n/m)
2
算法总体思想
对将这求出k个的子小问规题模分的别问求题解的。解如合果并子为问一题个的更规大模规仍模然的不问够 小题,的则解再,划自分底为向上k个逐子步问求题出,原如来此问递题归的的解进。行下去,直 到问题规模足够小,很容易求出其解为止。
{ if (left<right) {//至少有2个元素 int i=(left+right)/2; //取中点 mergeSort(a, left, i); mergeSort(a, i+1, right); merge(a, b, left, i, right); //合并到数组b copy(a, b, left, right); //复制回数组a }
15
棋盘的识别
首先,子棋盘的规模是一个必要的信息,有了这个 信息,只要知道左上角的方格在原棋盘中的行、列 号就可以标识这个子棋盘了;其次子棋盘中残缺方 格或“伪”残缺方格直接用它们在原棋盘中的行、 列号标识。 ①tr表示棋盘左上角方格的行号; ②tc表示棋盘左 上角方格的列号 ③dr表示特殊方格所在的行号 ④dc 表示特殊方格所在的列号, ⑤size表示方形棋盘行 数或列数。
T(n)
=n
n/m
n/m
n/m n/m
T(n/mT2)(n/mT2)(n/mT2)(n/m2) T(n/mT2)(n/mT2)(n/mT2)(n/m2)T(n/mT2)(n/mT2)(n/mT2)(n/m2T) (n/mT2)(n/mT2)(n/m4 T2)(n/m
算法总体思想
将求出的小规模的问题的解合并为一个更大规模的问 题的解,自底向上逐步求出原来问题的解。
分治法的适用条件
分治法所能解决的问题一般具有以下几个特征: • 该问题的规模缩小到一定的程度就可以容易地解决; • 该问题可以分解为若干个规模较小的相同问题,即该
问题具有最优子结构性质 • 利用该问题分解出的子问题的解可以合并为该问题的
解; 这•条该特问征题涉所及分到解分出治的法各的个效子率问,题如是果相各互子独问立题的是,不即子问 独立题的之,间则不分包治含法公要共做的许子多问不题必。要的工作,重复地 解用公动共态因而这可能如可的规为 增 条 以 否 果 以子划问加特满利具考问较题,征足用备虑题好贪的因是的分了,。计此应,治前心此算大用此法两算时复部分特完条法虽杂分治征全特或然性问法反取征动也一题的映决,态可般满前了于而规用是足提递问不划分随这,归题具。治着个它思是备法问特也想否第,题征是的具三但规。大应有条一模多用这特般的数条征增问特,加题征则,
6
分治法的基本步骤
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); //递归的解各子问题
}
11
合并排序
算法mergeSort的递归过程可以消去。 初始序列 [49] [38] [65] [97] [76] [13] [27]
第一步 第二步
[38 49] [65 97] [13 76] [27]
[38 49 65 97]
[13 27 76]
第三步
[13 27 38 49 65 76 97]
int特殊方格在此棋盘中chessboardtrtcdrdc号l型骨牌覆盖右下角boardtr覆盖其余方格chessboardtrtctrs1tcs1特殊方格在此棋盘中chessboardtrtcsdrdc号l型骨牌覆盖左下角boardtr覆盖其余方格chessboardtrtcstrs1tcs特殊方格在此棋盘中chessboardtrstcdrdc号l型骨牌覆盖右上角boardtr覆盖其余方格chessboardtrstctrstcs1特殊方格在此棋盘中chessboardtrstcsdrdc号l型骨牌覆盖左上角boardtr覆盖其余方格chessboardtrstcstrstcs18循环赛日程表循环赛日程表设计一个满足以下要求的比赛日程表
board[tr + s - 1][tc + s - 1] = t;
chessBoard(tr+s, tc, tr+s, tc+s-1, s);}
// 覆盖其余方格
// 覆盖右下角子棋盘
chessBoard(tr, tc, tr+s-1, tc+s-1, s);} if (dr >= tr + s && dc >= tc + s)
每执行一次算法的while循环, 待
int m = (l+r)/2;
搜索数组的大小减少一半。因此,
if (x == a[m]) return m;
在最坏情况下,while循环被执行了
if (x < a[m]) r = m-1; else l = m+1; O(logn) 次。循环体内运算需要O(1)
按分治策略,将所有的选手分为两半,n个选手的比赛日程表
就可以通过为n/2个选手设计的比赛日程表来决定。递归地用
对选手进行分割,直到只剩下2个选手时,比赛日程表的制定
就变得很简单。这时只要让这2个选手进行比赛就可以了。
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
else {// 此棋盘中无特殊方格
4T
(k
O/c/(h特1e)s殊sB方o格ar在d(此tkr+棋s,盘t0c中, dr, dc, s); elbs1eo)a{r/d/ [用Otr +(t1号s)][Ltc型k+骨s牌-0覆1] 盖= t右; 上角
// 用 t 号L型骨牌覆盖T(右n下)=角O(4k) 渐进意// 覆义盖下其的余方最格优算法
10
合并排序
基本思想:将待排序元素分成大小大致相同的2个子集合,分 别要对求2的个排子好集序合的进集复行合杂排。度序分,析最T (终n)将 排2好T (序n /O的2()1子) O集(n合) 合nn 并 11成为所 void MergeSort(Type a[], int lTef(t,nin)=t rOigh(nt)logn) 渐进意义下的最优算法
规模不等的做法要好。
7
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。 分析: 该问题的规模缩小到一定的程度就可以容易地解决;
该问题可以分解为若干个规模较小的相同问题;
分解出的子问题的解可以合并为原问题的解; 分析:分比解较出x和的a各的个中子间问元题素是a[相mi互d]独,立若的x=。a[mid],则x在L中的 位置就是mid;如果x<a[mid],由于a是递增排序的,因此假 分可用如a的分面用[m析以条x后析或条在id:确件面:后件]a的定查面。如很中前找查果x显的是面找然nx话否即=查此x,1在可是即找问x表。独必只x题即中无立然有分可。论的排一解;因是子在个出如此在问a元的[果m这前题素子ixd个面,,>]问的a问还因则[题i前]题是此,只相面满后满同要互,足面足理比独所分查分我较立以治找治们这,我法法x只个,即们的的要元其在只第第在素方a要一四[a和i法][在的m个个x都就i前适适d] 和在a中查找x一样,只不过是查找的规模缩小了。这就说明 了此问题满足分治法的第二个和第三个适用条件。
16
棋盘数据结构
• 用二维数组Board[][]来模拟棋盘,Board[1][1]是棋盘的左上角方格。 title表示L 型骨牌的编号,其初始值为0。覆盖残缺棋盘所需要的三格 板数目为:(size*size -1)/3。将这些 三格板编号为1到(size*size-1)/3, 则将覆盖残缺棋盘的三格板编号存储在数组Board的对应位置,这样 输出数组内容就是问题的解。如果是一个4 ×4的棋盘,特殊方格为 (2,1),那么程序的输出为对于如图8-6(a)所示的棋盘,其结果为8-6(b) 所示的棋盘。其中特殊方格为0,相同数字的为同一骨牌。
17
棋盘覆盖
void chessBoard(int tr, int tc, int dr, int dc, int size)
{
board[tr + s - 1][tc + s] = t;
if (size == 1) return;
// 覆盖其余方格
int t = tile++, // L型骨牌号
chessBoard(tr, tc+s, tr+s-1, tc+s, s);}
s = size/2; // 分割棋盘
// 覆盖左下角子棋盘
// 覆盖左上角子棋盘
if (dr >= tr + s && dc < tc + s)
if (dr < tr +复s &杂& 度dc 分< tc析+ s)
/c/h特es殊sB方o格ar在d(此tr,棋tc盘, d中Tr, d(ck,)s);
8
二分搜索技术
给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找 出一特定元素x。
据此容易设计出二分搜索算法:
template<class Type>
int BinarySearch(Type a[], const Type& 算x, in法t l,复int杂r) 度分析:
{ while (r >= l){