问题:
解题:
分析:从最简单的开始分析,若是1个盘子的时候终止条件,剩下的先分析2个盘子和3个盘子的情况,正向分析不好分析,采用递归思想,倒序思考,要处理n个盘子从A到C,就是先把n-1个盘子从A到B,然后把A的第n大的盘子移动到C,然后再将n-1个盘子B到C,如此往复,最终需要移动2^n-1次移动
@Slf4j
public class Solution {
public final AtomicInteger count = new AtomicInteger(0);
public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {
TowerOfHanoiPillar pillarA = new TowerOfHanoiPillar(A, "A");
TowerOfHanoiPillar pillarB = new TowerOfHanoiPillar(B, "B");
TowerOfHanoiPillar pillarC = new TowerOfHanoiPillar(C, "B");
exchange(pillarA, pillarB, pillarC, A.size());
}
private void exchange(TowerOfHanoiPillar pillarA, TowerOfHanoiPillar pillarB, TowerOfHanoiPillar pillarC, int n) {
if (n == 1) {
// 如果A还剩1个,判定最小的,放入C
a2C(pillarA, pillarB, pillarC, n);
} else {
// 1.如果A最大的以上移动到B
exchange(pillarA, pillarC, pillarB, n - 1);
// 2.将A上最大的移动到C上
a2C(pillarA, pillarB, pillarC, n);
// 3.将B上所有盘子移动到C
exchange(pillarB, pillarA, pillarC, n - 1);
}
}
private void a2C(TowerOfHanoiPillar pillarA, TowerOfHanoiPillar pillarB, TowerOfHanoiPillar pillarC, int n) {
int num = count.incrementAndGet();
List<Integer> listA = pillarA.getList();
String nameA = pillarA.getName();
int index = listA.size() - 1;
int number = listA.get(index);
List<Integer> listC = pillarC.getList();
String nameC = pillarC.getName();
log.info("count{},n:{}===移动前 [{}]-{}->[{}] === {},{},{}", num, n, nameA, number, nameC, pillarA, pillarB, pillarC);
listC.add(listA.remove(index));
log.info("count{},n:{}===移动后 [{}]-{}->[{}] === {},{},{}", num, n, nameA, number, nameC, pillarA, pillarB, pillarC);
}
}
@Data
@AllArgsConstructor
public class TowerOfHanoiPillar {
private List<Integer> list;
private String name;
}
public class TestHanNuoTa {
public static void main(String[] args) {
Solution solution = new Solution();
ArrayList<Integer> a = new ArrayList<>();
a.add(5);
a.add(4);
a.add(3);
a.add(2);
a.add(1);
ArrayList<Integer> b = new ArrayList<>();
ArrayList<Integer> c = new ArrayList<>();
solution.hanota(a, b, c);
System.out.println("A="+a);
System.out.println("B="+b);
System.out.println("C="+c);
}
}
性能:
递归比较占用内存,跟着这个程序走,汉诺塔小游戏可以通关了,不过层数太多,递归就会导致内存爆炸