分治算法
-
分治法,字面意思是“分而治之”,就是把一个复杂的问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题直到最后子问题可以简单地直接求解,原问题的解即子问题的解的合并。
-
由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。这自然导致递归过程的产生。分治与递归经常同时应用在算法设计之中。
-
分治法使用场景:
该问题的规模缩小到一定的程度就可以容易的解决。
该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
利用该问题分解出的子问题的解可以合并为该问题的解。
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。 -
分治法的基本步骤
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题。
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
合并:将各个子问题的解合并为原问题的解
汉诺塔游戏
在汉诺塔游戏中,有三个分别命名为A、B、C得塔座,几个大小各不相同,从小到大一次编号得圆盘,每个原盘中间有一个小孔。最初,所有得圆盘都在A塔座上,其中最大得圆盘在最下面,然后是第二大,以此类推.
游戏的目的是将所有的圆盘从塔座A移动到塔座C;塔座B用来放置临时圆盘,游戏的规则如下:
1、一次只能移动一个圆盘
2、任何时候都不能将一个较大的圆盘压在较小的圆盘上面.
3、除了第二条限制,任何塔座的最上面的圆盘都可以移动到其他塔座上.
分析:
A上有4个圆盘:
先将前三个圆盘从A移动到B,然后圆盘4从A移动到C,前三个圆盘再从B再移动到C.
但是上面的步骤可以重复利用!
例如将三个圆盘从A移动到C,那么应该先将前两个圆盘从A移动到B,然后将圆盘3从A移动到C,最后将前两个圆盘从B移动到C.
例如将2个圆盘从A移动到C,那么应该先将前 1个圆盘从A移动到B,然后将圆盘 2从A移动到C,最后将前 1个圆盘从B移动到C.
持续简化这个问题,最终我们将只需要处理一个圆盘从一个塔座移动到另一个塔座的问题.
当盘子数n>=2 ,那我们将A上的圆盘分为两部分,最下面第n 个盘子的和它上面的n-1个盘子 ,实际执行三大步:
- 实现这个算法可以简单分为三个步骤:
(1) 把n-1个盘子由A 移到 B;
(2) 把第n个盘子由 A移到 C;
(3) 把n-1个盘子由B 移到 C;
package 分治算法;
//汉诺塔游戏
public class HanNuoTa {
public static void main(String[] args) {
tower(2, 'A', 'B', 'C');
}
/*输出:
第1个盘子从A移动到B
第2个盘子从A移动到C
第1个盘子从B移动到C*/
/**
* @param num 盘子的数量
* @param a A塔
* @param b B塔
* @param c C塔
*/
//要从A塔移到C塔,中间会借助到B塔 注意顺序: 从A到C,借助B
public static void tower(int num,char a,char b,char c) {
//如果只有一个盘
if(num==1) {
System.out.println("第1个盘子从"+a+"移动到"+c);
}
else {//当盘子数n>=2 ,那我们将A上的圆盘分为两部分,最下面第n 个盘子的和它上面的n-1个盘子
// (1) 把n-1个盘子由A 移到 B,移动过程会借助到到C
tower(num-1, a, c, b);
// (2) 把第n个盘子由 A移到 C;
System.out.println("第"+num+"个盘子从"+a+"移动到"+c);
// (3) 把n-1个盘子由B 移到 C ,移动过程会借助到到A
tower(num-1, b, a, c);
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!