问题描述:Hanoi塔包括一对尺寸不等的圆盘和三个分别为A B C的针,初始状态为n个圆盘放在针A上。现在要讲圆盘从针A移动到针C上,一次只能用移动一个圆盘,并且一相同的顺序重新构建n个圆盘。在移动圆盘时,尺寸大的圆盘不允许放在尺寸小的圆盘上。
通常移动N个圆盘的算法需要移动2的n次方-1.
假以3个盘子的问题递归求解:
hanoi(int n,String initNeedle,String endNeedle,Strign tempNeedle);
分成三个阶段
1 使用三次移动将针A上面的两个圆盘移动到针B上
hanoi(n-1,initNeedle,tempNeedle,endNeedle);
2 使用一次简单的移动将针A上面的最大圆盘移动到针C上(终止条件)
3 使用三次移动将针B上面的两个圆盘移动到针C上
hanoi(n-1,tempNeedle,endNeedle,initNeedle);
package edu.cumt.jnotnull;
public class Hanoi {
public static void hanoi(int n,String initNeedle,String endNeedle,String tempNeedle){
if(n == 1){
System.out.println("move "+initNeedle+" to " +endNeedle);
}
else{
hanoi(n-1,initNeedle,tempNeedle,endNeedle);
System.out.println("move "+initNeedle+" to "+endNeedle);
hanoi(n-1,tempNeedle,endNeedle,initNeedle);
}
}
/**
* @param args
*/
public static void main(String[] args) {
int n = 3;
String beginNeedle = "A";
middleNeedle = "B";
endNeedle = "C";
hanoi(n,beginNeedle,endNeedle,middleNeedle);
}
}
复杂度分析
从n个盘子开始,将发生多少次移动?
令m(n)表示该算法解决n个盘子的问题所需的移动次数,很明显
m(1) = 1
对于n>1 算法使用了两个递归调用分别解决了两个n-1个盘子的问题,其中每个问题所需的移动次数都是m(n-1).因此从算法中可以看出
m(n)=m(n-1)+1+m(n-1) = 2m(n-1)+1
从这个等式中可见m(n) > 2m(n-1).也就是说 解决n个盘子的问题所需移动次数比解决n-1个盘子的问题多过两倍
按照m(n)=m(n-1)+1+m(n-1) = 2m(n-1)+1进行推算
m(1) =1;m(2)=3;m(3)=7;m(4)=15;m(5)=31;m(6)=63;
从而m(n) = 2^n -1
使用数学归纳法也能推出:
m(1) = 1; 2^1 - 1 = 1;所以该推测对于n=1成立
现在假使对于n=1,2,3...k,推测都是正确,现证明对m(k+1)也正确
m(k+1) = 2m(k)+1 = 2(2^k -1)+1 = 2^(k+1)-1
因为据推测对于n=k+1也是正确的,所以对于所有的n>=1都是正确的