分治算法介绍
何为分治算法,简单来说,就是将一个大的问题,分解成一个个小的相似问题,然后逐个求解出各个小问题的解,再将各个小问题的解,合并为一个解。
将问题分成子问题等方式求解,和递归的概念比较吻合,所以分治的问题一般也是使用递归求解。
- 分:递归到最小问题。
- 治:逐个解决问题。
- 合并:将问题的解构建为大问题的解。
分治算法经典问题(汉诺塔)
首先,什么是汉诺塔呢?
汉诺塔的传说:大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
类似如下图片
如何解决把A塔的盘放到C塔
首先我们来考虑盘数<=2的时候,该如何解决;
- 首先假设我们如果只有一个盘,那绝对很简单,把A塔的盘子直接放到C塔
- 如果有两个盘呢,那我们需要借助B塔,先把A塔上面的盘放置到B塔,然后把A塔下面的盘放置到C塔,最后把B塔的盘放置到C塔。
以上是当盘数<=2的情况,那当盘数>2的时候我们该如何解决呢?
- 首先我们需要把当前的盘数想象成只有两个盘,分别最下面的一个盘,和上面的所有盘。
用一张图表示
- 然后先将A塔上面的所有盘放置到B塔,再将最下面的盘放置到C塔,最后将B塔的所有盘放置到C塔。
依次将大的问题分解为小的问题,最后得到解。
代码实现:
public class HanoiTower {
public static void main(String[] args) {
hanoiTower(4,'a','b','c');
}
/**
* 汉诺塔
* 思路分析:1、如果只有一个盘,直接从 a -> c 解决问题
* 2、两个盘的移动方法,把上面的盘从 a -> b,把下面的盘从 a -> c,把b的盘 -> c
* 3、如果有两个盘以上,把它想象成只有两个盘,最下面的盘,和上面的所有盘,再按照第二步执行。
*
* @param num 盘数
* @param a a柱
* @param b b柱
* @param c c柱
*/
public static void hanoiTower(int num, char a, char b, char c) {
if (num == 1) {
System.out.println("第" + num + "个盘从 " + a + " -> " + c);
return;
}
//把上面的盘从a柱移动到b柱,借助c柱
hanoiTower(num - 1, a, c, b);
//把最下面的盘从a柱子移动到c柱
System.out.println("第" + num + "个盘从 " + a + " -> " + c);
//把b柱的所有盘移动到c柱子,借助a柱
hanoiTower(num - 1, b, a, c);
}