分治算法
韩顺平数据结构算法与笔记
介绍
把一个复杂的问题分解成两个或者多个相同或相似的小问题,再把小问题划分成更小的问题
分治算法可以求解的一些经典问题
二分搜索
大整数乘法
棋盘覆盖
合并排序
快速排序
线性时间选择
最接近点对问题
循环赛日程表
汉诺塔
难点:怎么把大问题划分成小问题
基本步骤
1)分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题
2)解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
3)合并:将各个子问题的解合并为原问题的解。
设计模式
if |P|< nO p代表问题的规模
then return(ADHOC(P))
//将P分解为较小的子问题P1 ,P2..
for i <-1 to k
do yi <- Divide-and-Conquer(Pi)递归解决Pi |
T <- MEREGE(12_,.yk)合并子问题
return(T)
其中|P|表示问题P的规模; n0为一阈值,表示当问题P的规模不超过n0时,. 问题己容
易直接解出,不必再继续分解。ADHOC§是该分治法中的基本子算法,用于直接解
小规模的问题P。~因此,当P的规模不超过n0时直接用算法ADHOC§求解。算法
MERE(y/,2y2.yk)是该分治法中的合并子算法,用于将P的子问题P1 ,P2 …k的相应
的解y.,2…yk合并为P的解。
应用案例——汉诺塔
思路
我们从只有一个盘开始推导
发现一个规律,我们可以把所有的盘看成只有两个盘,最下面的盘和上面所有的盘
而且,总是把最下边的盘移动到第三个柱子上,然后把剩下上面的盘移动到第三个盘上就行了
package 算法;
//汉诺塔---------分治算法
public class DAC {
public static void main(String[] args) {
hanoiTower(6, 'A', 'B', 'C');
}
/**
//汉诺塔的移动方案 -- 分治算法
* @param num 盘子数目
* @param a 第一个柱子
* @param b 第二个柱子
* @param c 第三个柱子
*/
public static void hanoiTower(int num,char a,char b,char c){
//如果只有一个盘
if(num == 1){
System.out.println("第一个盘从"+a+"->"+c);
}else{
//如果是 num>=2的情况,我们总是可以看做两个盘,最下面的盘和上面所有盘
//1.先把最上面的所有盘A->B
hanoiTower(num-1, a, c, b);
//2.把最下面的盘从A移动到C
System.out.println("第"+num+"个盘从"+a+"->"+c);
//3.把B塔所有盘--->C 移动过程使用到A塔
hanoiTower(num-1, b, a, c);
}
}
}
这个地方一定不能迷,我们在递归的时候,从那个柱子移动到那个柱子就是递归的时候前后位置一定要注意,a->c那就是abc a->b那就是acb,我们不能纠结这样写为啥就移上去了,自己知道流程就好