一、递归思想
递归思想,其中最重要的大事化小的思想,递归实际上就是把一个复杂问题变成简单问题的过程。在用递归思想解决问题时需要注意的一点就是我们不需要纵向思考,只需要横向思考,什么意思呢,就是我们没有必要去一步步去理清解决这个过程的每一步,因为我们本身要解决的问题的复杂通过自身思维直接思考是难以理清的,如果很容易展开,这个问题就没必要用到递归思想。所以,在使用递归思想的时候,应该抛去原有思考问题的方式,只要找到问题中的规律然后用代码实现后以计算机的结果来判断是否思考正确即可。
二、以递归思想的方式思考汉诺塔问题
汉诺塔我想大家小时候都玩过或者见过,无非就是三个柱子,然后上面有圆盘,要始终保持大盘在下小盘在上的同时使所有的圆盘从第一个柱子借助第二根柱子转移到第三根柱子。
我们先从简单问题开始思考,如图,设三个柱子分别为a,b,c;要移动一个圆盘,两个圆盘,三个圆盘,分别要经过几步且步骤是什么。
这里我就不都画图了,我们直接来讨论
一个盘子的情况:
很简单,从A移到C即可,步骤为A -> C,总共需要1步
两个盘子的情况:
首先得把最上方的盘子移到B中,再将最下面的盘子移到C中,最后将B中的盘子移到C中,步骤为A -> B,A -> C,B ->C,总共需要三步。
三个盘子的情况:
先将最上方的盘子移到C中,再将第二个盘子从A移到B中,然后将C盘中的盘子移到B中,到这里实现了上方两个盘子移到了B中,现在再将A中剩下的最大盘子移到C中,最后只要按规则使B中两个盘子移到C中即可,这里三个盘子的步骤我故意不写出来,接下来会讲为什么,我只说步骤需要7步。
重点来了,我们现在通过上面三种情况能够知道的是圆盘的数目和需要移动几步构成关系m= 2的n次方减一(m为移动步数,n为圆盘数目),所以如果当圆盘的数目逐渐增加,移动步数是急剧增加的,假设现在有10个圆盘,移动步数就为2的十次方减一,试问,这是我们通过自己的脑子能想清楚的问题吗?所以,刚刚三个盘子时我就不再写出步骤,就是不想你们陷入这种思考中,我们不需要去思考其中具体的过程。
只要这个思维正确了,我们就很容易可以解决这个问题了,移动三个盘子,我们是不是先把两个盘子移到了B中,再将A中的盘子移到C中,最后将两个盘子从B移到C中。好那我们现在来想想n个盘子的情况,是不是将n-1个盘子移到B中,然后将仅剩的盘子从A移到C中,我们需要思考n-1是怎么移到B中的吗?不需要,将n-1个盘子移到B,问题不就变成先将n-2个盘子移到C中了吗,以此类推,我们只需要将递推公式想清楚,写代码,让计算机帮我们去实现过程即可,千万不要试图以人脑去想清楚每一步是怎么进行的。
三、代码实现
```java
public class Hanoi {
public static void hanoi(int n, char pos1, char pos2, char pos3) {
if(n == 1) {
move(pos1,pos3);
return;
}
hanoi(n-1,pos1,pos3,pos2);
move(pos1,pos3);
hanoi(n-1,pos2,pos1,pos3);
}
public static void move(char posStart, char posEnd) {
System.out.println(posStart + "->" + posEnd);
}
public static void main(String[] args) {
hanoi(1, 'a', 'b', 'c');
System.out.println("==============");
hanoi(2, 'a', 'b', 'c');
System.out.println("==============");
hanoi(3, 'a', 'b', 'c');
}
}