一、介绍
1)
分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题
……
直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法
(
快速排序
,
归并排序
)
,傅立叶变换
(
快速傅立叶变换
)……
2)
分治算法可以
求解的一些经典问题
•
二分搜索
•
大整数乘法
•
棋盘覆盖
•
合并排序
•
快速排序
•
线性时间选择
•
最接近点对问题
•
循环赛日程表
•
汉诺塔
分治算法的基本步骤
分治法在每一层递归上都有三个步骤:
1)
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题
2)
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
3)
合并:将各个子问题的解合并为原问题的解。
二、分治算法的实践-汉诺塔
汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
汉诺塔游戏的
演示
和
思路分析
:
如果我们有 n >= 2
情况,我们总是可以看做是两个盘
1.
最下边的盘
2.
上面的所有盘
1)
先把 最上面的盘
A->B
2)
把最下边的盘
A->C
3)
把
B
塔的所有盘 从
B->C
三、代码演示
class hanoiTower{
static long count;
//移动n个盘,a为起始柱子,b为辅助柱子,c为目标柱子
public static void hanoiTower(int n,char a,char b,char c){
//只有一个盘时,直接a->c
if(n==1){
count++;
System.out.println("第1个盘:"+a+"->"+c+" "+count);
}
else{
//有多个盘时,把最下面的盘看成一个盘X,其上面所有盘看成另一组Y。
//先把Y移到辅助柱子上,再把X移动到目标柱子上,最后把Y移到X上面
//1. Y 从a->b,c作为辅助柱子
hanoiTower(n-1,a,c,b);
//2. X 从a->c,不用b
count++;
System.out.println("第"+n+"个盘:"+a+"->"+c+" "+count);
//3. Y 从b->c,a作为辅助柱子
hanoiTower(n-1,b,a,c);
}
}
}
@Test
public void test(){
hanoiTower.hanoiTower(5,'a','b','c');
}
第1个盘:a->c 1
第2个盘:a->b 2
第1个盘:c->b 3
第3个盘:a->c 4
第1个盘:b->a 5
第2个盘:b->c 6
第1个盘:a->c 7
第4个盘:a->b 8
第1个盘:c->b 9
第2个盘:c->a 10
第1个盘:b->a 11
第3个盘:c->b 12
第1个盘:a->c 13
第2个盘:a->b 14
第1个盘:c->b 15
第5个盘:a->c 16
第1个盘:b->a 17
第2个盘:b->c 18
第1个盘:a->c 19
第3个盘:b->a 20
第1个盘:c->b 21
第2个盘:c->a 22
第1个盘:b->a 23
第4个盘:b->c 24
第1个盘:a->c 25
第2个盘:a->b 26
第1个盘:c->b 27
第3个盘:a->c 28
第1个盘:b->a 29
第2个盘:b->c 30
第1个盘:a->c 31