Java 如何用河内塔调用递归

Java 如何用河内塔调用递归,java,recursion,towers-of-hanoi,Java,Recursion,Towers Of Hanoi,我正在努力解决河内塔的问题;我写了这段代码: public class TowersOfHanoi { public static void main(String[] args) { move(5, 1, 3); } public static void move(int disks, int from, int to) { if (disks > 0) { int other = 6 - from - to; // s

我正在努力解决河内塔的问题;我写了这段代码:

public class TowersOfHanoi {
   public static void main(String[] args) {
      move(5, 1, 3);
      }

   public static void move(int disks, int from, int to) {
      if (disks > 0) {
         int other = 6 - from - to; // sum of index 1+2+3=6
         System.out.println("Move disk from peg " + from + " to " + to);
         move(disks - 1, from, other);
         move(disks - 1, other, to);
         }
   }
}
但结果是错误的。我书中的解决方案是

public class TowersOfHanoi {
   public static void main(String[] args) {
      move(5, 1, 3);
      }

   public static void move(int disks, int from, int to) {
      if (disks > 0) {
         int other = 6 - from - to; // sum of index 1+2+3=6
         move(disks - 1, from, other);
         System.out.println("Move disk from peg " + from + " to " + to);
         move(disks - 1, other, to);
         }
   }
}
为什么会这样?我无法理解这些表达的顺序:

  • 首先运行
    System.out.println()
  • 然后运行
    move(磁盘-1,from,other)
  • 现在它再次运行
    System.out.println()
    ,或者运行
    move(disks-1,other,to)

什么时候重新启动块代码?Thanx.

正确的解决方案是:

  • 首先,您必须递归地将顶部的n-1个光盘从“peg from”移动到“peg other”
  • 然后,您可以将底部光盘从peg“from”移动到peg“to”-这是
    println
    语句
  • 然后,您必须将n-1个光盘(在步骤1中移动)从peg“other”移动到peg“to”

  • 另一方面,在错误的解决方案中,您试图做的是在移动堆叠在其上的所有光盘之前移动底部光盘,这是无效的移动。

    河内塔的工作方式是-:

  • 首先,您必须使用3将n-1个磁盘从第一个移动到第二个peg
  • 将最后第n个磁盘移动到第3个peg
  • 使用1st将n-1磁盘从第二个销钉移动到第三个销钉
  • 这本书的解答是正确的。您的解决方案是错误的,因为您在开始时移动了最后一个磁盘,这违反了河内塔的规则。我希望你能得到它

    经过一些修改后的代码更加优雅易懂,适用于任意的n。(由于指数复杂性,至少适用于较小的n值)


    因此,我们有
    n
    磁盘和3个peg,我们希望将放置在第一个peg(源peg)中的磁盘移动到第三个peg(目标peg);在这种情况下,递归的概念是:

  • 将所有磁盘从1递归地移动到最大磁盘(称为
    n
    )上方的
    n-1
    ,从第一个peg移动到第二个peg(备用peg),因为我们希望为最大的磁盘腾出空间,并能够将其放入第三个peg。这是移动(磁盘-1,从,其他)的第一句话
    move

  • 在将所有磁盘移到最大磁盘上方后,我们将其移到第三个peg:作为Wikipedia,这是简单的步骤,也是第二句话
    System.out.println(“将磁盘从peg+从+”移动到“+到”)

  • 最后,将所有
    n-1
    磁盘从第二个peg递归地移动到第三个,以便在第三个peg中重新创建塔,最后一句
    移动(磁盘-1,其他,移动到)

  • 该算法适用于奇偶
    n
    磁盘,因为它是一个通用的求解过程,显然,步骤将根据磁盘的初始数量而变化。

    可能调试器将帮助您了解递归的工作原理。只需在println语句中打印
    disks
    值,以更好地理解整个序列。我已经试着理解您的算法一个多小时了,但我有一些问题:在第一个递归
    n-1
    磁盘是第一个peg顶部的较小磁盘?或者我必须把上面的第一个磁盘看作是<代码> n<代码>,其他的作为代码> n-1 < /代码>,直到底部最大的磁盘为止。因此,最上面或最小的磁盘是1,而最下面(最大)的磁盘是n。所以在第一步中,我们得到了第一个顶部的n-1磁盘(编号从1到n-1)。然后将第n个(底部最大的)放在Ok位置,这样,如果在第一步中有n=5个磁盘,我将选择4个磁盘(disk1-disk2-disk3-disk4),其中disk1最小?。是的,您必须在第一步中移动磁盘1、磁盘2、磁盘3、磁盘4(n-1)磁盘。但这一步是递归调用,它肯定会将所有磁盘(1-4)放在PEG2上。如果你不能理解它,举一个小例子。对于n=1,这是微不足道的。对于n=2,您已经将上述n-1个磁盘,即磁盘1放置到第二个peg,将磁盘1移动到第三个peg,然后将第二个磁盘移动到第三个peg。对于n=3,在第一步中调用递归将递归地移动n-1个磁盘,即磁盘1和磁盘2。然后必须将第三个磁盘移动到第三个peg(即打印移动),然后再次将n-1个磁盘从第二个peg移动到第三个peg(这将通过递归完成)。信任递归为您工作。为什么?如果你想知道n个磁盘和3个PEG需要多少步,那么它就是$2^{n}-1$。这是由于递归方程$T(n)=T(n-1)+1+T(n-1)$或$T(n)=2T(n-1)+1$,求解它。您还可以修改方法以返回int(这将给您提供步骤数)。假设T(n)作为与算法时间复杂度相关的访问数,第一个T(n-1)表示第一步,+1表示打印步骤,第二个T(n-1)表示最后一步,对吗?是的。这是正确的。好。我不希望解释我上面写的内容,你完全理解。好的,请你解释一下你是如何从T(n)=2T(n-1)+1得到2^{n}-1的?我想这会帮助你理解整个解决方案。这里给出了非常详细的解释。
    public class TowersOfHanoi {
       public static void main(String[] args) {
          int first = 1, second = 2, third = 3;
          int disk = 5; // or take user input
          move(disk, first, third);
       }
    
       public static void move(int disks, int first, int second, int third) {
          if (disks > 0) {
                  move(disks - 1, first, third, second); // source = first, dest = second
                  System.out.println("Move disk from peg " + first+ " to " + third);
                  move(disks - 1, second, first, third);  // source = second, dest = third
             }
       }
    }