题目:

有三根杆,编号x,y,z,在x杆上自下而上、由大到小顺序放置着n个盘子,请问怎样能将所有盘子从x杆移动到z杆?

要求移动过程中每次只能移动一个盘子,且三根杆上的盘子要始终保持大盘在下,小盘在上(意思就是每次只能移动一个,并且只能将小盘放在比他大的盘子上)

思路:

这类问题一看就是一个规律题,我们首先要从最简单的场景寻找它的规律。

如果只有2个盘子,小的是1,大的是2。三根柱子分别是x,y,x。
移动过程:
1、1从x移动到y
2、2从x移动到z
3、1从y移动到z

将上述的1看成是前n-1个, 2看成是第n个,带入有3个盘子时的移动过程:

1、1从x—>z
2、2从x—>y
3、1从z—>y //到这里是前n-1从x移动到y
4、3从x—>z //这一步是第n个从x移动到z
5、1从y—>x
6、2从y—>z
7、1从x—>z //后面这几步是前n-1个从y移动到z

为什么能这样分?

因为第n个是最大的,而最大的能承载所有其余盘子,所以第n个能做为一个分界点。摆正了它的位置,后面移动过程中就不用动它了。
然后前面的n-1个又能找出第n-1大的盘子,作为剩余这些盘子中最大的,移动到z。所以就造就了这个递归循环。

分治思想

代码:

  1. package com.example.demo.core.Leecode;
  2. /**
  3. * @author: HanXu
  4. * on 2022/2/25
  5. * Class description: 汉诺塔:有三根杆,编号x,y,z,在x杆上自下而上、由大到小顺序放置着n个盘子,请问怎样能将所有盘子从x杆移动到z杆?
  6. * 要求移动过程中每次只能移动一个盘子,且三根杆上的盘子要始终保持大盘在下,小盘在上(意思就是每次只能移动一个,并且只能将小盘放在比他大的盘子上)
  7. *
  8. */
  9. public class HanoiDemo {
  10. public static void main(String[] args) {
  11. hanoi(3, 'x', 'y', 'z');
  12. }
  13. public static void hanoi(int n, char x, char y, char z) {
  14. //将问题分为两个:1、如果只有1个盘子 2、如果不止一个盘子
  15. if (n == 1) {
  16. System.out.println(x + "-->" + z);
  17. } else {
  18. //如果盘子数大于1,那么分三步走:
  19. //1、将前n-1个盘子从x移动到y
  20. hanoi(n - 1, x, z, y);
  21. //2、将第n个盘子从x移动到z
  22. System.out.println(x + "-->" + z);
  23. //3、将剩余n-1个盘子从y移动到z
  24. hanoi(n - 1, y, x, z);
  25. }
  26. }
  27. }
  28. /*
  29. 如果只有2个,小的是1,大的是2.三根柱子分别是x,y,x
  30. 移动过程:
  31. 1、1从x移动到y
  32. 2、2从x移动到z
  33. 3、1从y移动到z
  34. 将上述的1看成是前n-1个, 2看成是第n个
  35. 代码中n为3时的移动过程:
  36. x-->z
  37. x-->y
  38. z-->y //到这里是前n-1从x移动到y
  39. x-->z //这一步是第n个从x移动到z
  40. y-->x
  41. y-->z
  42. x-->z //后面这几步是前n-1个从y移动到z
  43. 为什么能这样分?因为第n个是最大的,而最大的能承载所有其余盘子,所以第n个能最为一个分界点,摆正它的位置,而后面移动过程中不用动。
  44. 然后前面的n-1个又能找出第n-1大的盘子,作为这些盘子中最大的,移动到z。所以就造就了这个递归循环。
  45. */
  46. /*
  47. x-->z
  48. x-->y
  49. z-->y
  50. x-->z
  51. y-->x
  52. y-->z
  53. x-->z
  54. */