递归思路打印汉诺塔步数
最近在看左程云视频,觉得好像会算法原型很吊哇,然后捏就一直卡在汉诺塔了,走不出来,好吧?
题目描述:
原始汉诺塔:
汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从上往下从小到大顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘,只能移动在最顶端的圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。
现在有n个圆盘从上往下从小到大叠在第一根柱子上,要把这些圆盘全部移动到第三根柱子要怎么移动呢?请找出需要步骤数最少的方案
思路:看到这题,一看就是递归,找原子操作不就行了吗?但是咋么下手分析呢?
首先拆分成3个原子问题:
1、当只有一个盘,那是不是我就直接从左边直接移动到右边就行了。这个不需要证明吧,原理来着,估计我是被带坏了,老想证明
现在拓展到n
思路我们都知道,就把n-1移动到中间,然后再把n移动到右边,再然后把n-1移到右边。这是可以理解的。但是呢?n-1移动到中间是什么操作,相对于我们来说貌似是个黑盒子操作?那接下来就是得分析怎么将n-1移动到中间了,其实呢?n-1看起来也是个符号来着,我们可以把它看作是n。
那么我们依照刚才的思路,n移动到中间,就是把n-1移动到右边,再把n移动到中间,再然后把n-1移动到中间,那我们是不是就解决这个黑盒子了
这就是我们的思路:
1 public static int traditionHanoiProblem1(int num,String left,String mid,String right){ 2 if (num<1) 3 return 0; 4 return traditionprocess(num,left,mid,right,left,right); 5 } 6 7 private static int traditionprocess(int num, String left, String mid, String right, 8 String from, String to) { 9 if (num==1){ 10 System.out.println("Move 1 from "+from+" to "+to); 11 return 1; 12 } 13 if (from.equals(mid) || to.equals(mid)){ 14 String another=(from.equals(left) || to.equals(left))?right:left; //这是关于第三种思考的,注意需要找到移到中间或者移离中间的中间柱,难点就在于此 15 int part1=traditionprocess(num-1,left,mid,right,from,another); 16 int part2=1; 17 System.out.println("move "+num+" from "+from+" to "+to); 18 int part3=traditionprocess(num-1,left,mid,right,another,to); 19 return part1+part2+part3; 20 }else { 21 int part1=traditionprocess(num-1,left,mid,right,from,mid); 22 int part2=1; 23 System.out.println("Move "+num+" from "+from +" to "+to); 24 int part3=traditionprocess(num-1,left,mid,right,mid,to); 25 return part1+part2+part3; 26 } 27 }
这是根据左神思路写的原始操作,在《程序员代码面试指南》中没有,接下来说说左神改题后的汉诺塔
题意:现在限制不能从最左侧的塔移动到最右侧,也不能从最右侧直接移动到最左侧,而是需要经过中间,这你觉得书上那个做法做起来好做吗?只有简单几行递归
但是呢?按我刚才的思路,特别好做。
思路:只是在上面的基础上更改右移的逻辑,即更改20行后的else逻辑。本来直接从左到右,现在需要经过中间,我加两行不就搞定了吗?
else {
int part1=traditionprocess(num-1,left,mid,right,from,to);
int part2=1;
System.out.println("Move "+num+" from "+from+" to "+mid);
int part3=traditionprocess(num-1,left,mid,right,to,from);
int part4=1;
System.out.println("Move "+num+" from "+mid+" to "+to);
int part5=traditionprocess(num-1,left,mid,right,from,to);
return part1+part2+part3+part4+part5;
}
有没有很通用的感觉呢?很舒服,也挺清晰,测试下代码逻辑是没错的,但如果有错误或者不谨慎,请指出。

浙公网安备 33010602011771号