分治算法
分治算法就是将原问题分解成n个规模较小,并且结构与原问题相似的子问题,再去递归地解决这些子问题,然后这些子问题,然后再合并其结果,就可以得到原问题的解。
分治算法的递归实现,每一层递归都会涉及一下三个操作:
- 分解:将原问题分解成一系列子问题
- 解决:递归地求解各个子问题,若子问题足够下,则可以直接求解
- 合并:将子问题地结果合并成原问题
分治算法能解决的问题,一般需要满足几个条件:
- 原问题与分解的子问题具有相同的模式(即就是求解问题的方式一样)
- 原问题分解的子问题可以独立求解,子问题之间没有相关性
- 具有分解终止条件,也就是说,当问题足够小时,可以直接求解
- 可以将子问题合并成原问题,而这个合并操作的时间复杂度不能太高,否则就起不到减小算法时间复杂度的效果了
接下来我们来看一个经典的分治问题:汉诺塔游戏
汉诺塔(Tower of Hanoi)是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
首先我们来看一个演示动图,来了解一下实现的整体流程:
对于这个问题我们首先从左到右将3个柱子记为x,y,z,要将 x上的n个长方体移动到z上,我们只需要将x上的前n-1个移动到y上,再将第n个移动到z上,接下来我们需要将y上的最后一个n-1的长方体快移动到z上,那只需要将y上的前n-2个移动到x上,在将第n-1个移动到z上…
依次类推知道将所有的长方体移动到z上
假如我们有64ge那么根据上面的思路就会有一下的流程依次类推就计算
最后我们以3层长方体块为例来看一下代码
public class RecursionDemo4 {
public static void main(String[] args) {
String x = "x";
String y = "y";
String z = "z";
hanoi(3,x,y,z);
}
private static void hanoi(int n, String begin, String mid, String end) {
if(n == 1){
//表示每一个长方体的移动过程
System.out.println(begin + "->" + end);
}else {
//通过递归在去走我们的n-1层的长方体块
hanoi(n-1,begin,end,mid);
System.out.println(begin + "->" + end);
hanoi(n-1,mid,begin,end);
}
}
}
运行结果: