汉诺塔算法是很多公司的面试题,经常会让手写,这里总结了一下
1、最最最常见的也是最简单的汉诺塔算法,递归(这也是学习递归的一个经典算法题)
/**
* 汉诺塔算法-递归
*
* ps:打印移动过程
* @param level 层数
* @param from 起始位置
* @param to 目标位置
* @param other 多出来的那个
* @return 需要的步数
*/
public static int move(int level,String from,String to,String other){
int step = 0;
if(level > 0){
//将level-1个移动到other上
step += move(level - 1,from,other,to);
//将最后一个一到to上
System.out.println(from+" ---> "+to+" ");
step+=1;
//再将刚移动到other上的level-1移动到to上
step += move(level - 1,other,to,from);
}
return step;
}
2.非递归算法,由递归算法演变而来,将递归时存储的线程快照又自己模拟存储
/**
* 汉诺塔算法-非递归
*
* ps:打印移动过程
* @param level 层数
* @param from 起始位置
* @param to 目标位置
* @param other 多出来的那个
* @return 需要的步数
*/
public static int move2(int level,String from,String to,String other){
int step = 0;
List<CommandSnapshot> snapshots = new ArrayList<>();
//添加所需要执行的移动命令
snapshots.add(new CommandSnapshot(level,from,to,other));
for (;;) {
//无移动命令可执行,则退出
if(snapshots.size()==0){
break;
}
//获取最新命令
CommandSnapshot snapshot = snapshots.remove(snapshots.size()-1);
//若只移动一个,则执行(汉诺只能一个一个移动)
if(snapshot.level == 1){
System.out.println(snapshot.from+" ---> "+snapshot.to);
step ++;
}
//移动多个的话,将其拆分成多个移动命令,并保存起来
else{
//这里倒序保存,因为上面获取最新命令是取的list的末尾
//生成命令3:将刚才移动到other上的level-1个再移动到to上
snapshots.add(new CommandSnapshot(snapshot.level-1,snapshot.other,snapshot.to,snapshot.from));
//生成命令2:将剩下的一个移动到to上
snapshots.add(new CommandSnapshot(1,snapshot.from,snapshot.to,snapshot.other));
//生成命令1:将level-1个移动到other上
snapshots.add(new CommandSnapshot(snapshot.level-1,snapshot.from,snapshot.other,snapshot.to));
}
}
return step;
}
/**
* 移动命令快照
*/
static class CommandSnapshot{
int level;
String from;
String to;
String other;
public CommandSnapshot(int level, String from, String to, String other) {
this.level = level;
this.from = from;
this.to = to;
this.other = other;
}
}
测试:
public static void main(String[] args) {
System.out.println("***********递归算法***********");
int step = move(3,"A","C","B");
System.out.println("步数:"+step);
System.out.println("***********非递归算法***********");
int step2 = move2(3,"A","C","B");
System.out.println("步数:"+step2);
}
运行结果:
***********递归算法***********
A ---> C
A ---> B
C ---> B
A ---> C
B ---> A
B ---> C
A ---> C
步数:7
***********非递归算法***********
A ---> C
A ---> B
C ---> B
A ---> C
B ---> A
B ---> C
A ---> C
步数:7