Double Java



我遇到了一个问题。当我得到这段代码时,我不明白该怎么想:

public class MysteryClass {
   public static void mystery(int n) {
      if (n > 0){
         mystery(n-1);
         System.out.print(n * 4);
         mystery(n-1);
      }
   }
   public static void main(String[] args) {
      MysteryClass.mystery(3);
   }
}

答案是 4 8 4 12 4 8 4 但我不知道他们是怎么得到的.. 有人可以解释一下吗?

这就是函数调用的方式。要了解更多,请拿一支铅笔和一张纸,画出发生了什么。首先,为神秘而做(1(。然后继续神秘(2(和神秘(3(

mystery(3)
    msytery(2)
        mystery(1)
            mystery(0)
            prints 1 * 4
            mystery(0)
        prints 2 * 4
        mystery(1)
            mystery(0)
            prints 1 * 4
            mystery(0)
    prints 3 * 4
    msytery(2)
        mystery(1)
            mystery(0)
            prints 1 * 4
            mystery(0)
        prints 2 * 4
        mystery(1)
            mystery(0)
            prints 1 * 4
            mystery(0)

mystery(int n) 方法中,你用

mystery(n-1);

在递归调用之间,您输出原始调用的值乘以 4。

这意味着即使在第一个输出之前,您也使用 n-1 再次调用该方法,并在调用中使用 n-1 再次调用该方法。第一个数字是第一次调用的第二次迭代。第二个数字是第一次迭代,依此类推。这很难用言语来解释。通过逐步调试,您可能会更成功地理解它。

想想前几个电话,模式很明显;

n = 3
mystery(n-1); ->
   // recursive call
   n = 2 
   mystery(n-1); ->
      // recursive call
      n = 1
      mystery(n-1); ->
         // inside recursion      
         n = 0 // Do nothing
      System.out.print(n * 4);  // = 4
      mystery(n-1);
         // inside recursion
         n = 0 // Do nothing
   System.out.print(n * 4);  // = 8
   mystery(n-1); ->
      // inside recursion
      n = 1
      mystery(n-1); ->
         // inside recursion
         n = 0 // Do nothing
      System.out.print(n * 4);  // = 4
      mystery(n-1);
         // inside recursion
         n = 0 // Do nothing

。你明白了

这很简单!

这是发生的情况:

mystery(n = 3):
    mystery(n = 2):
        mystery(n = 1):
            mystery(n = 0):
                n > 0 = false
            << done with mystery(n = 0)
            PRINT n * 4 = 4
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            << done with mystery(n = 1)
        PRINT n * 4 = 8 
        mystery(n = 1):
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            PRINT n * 4 = 4
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            << done with mystery(n = 1)
        << done with mystery(n = 2)
    PRINT n * 4 = 12
    mystery(n = 2):
        mystery(n = 1):
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            PRINT n * 4 = 4
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            << done with mystery(n = 1)
        PRINT n * 4 = 8 
        mystery(n = 1):
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            PRINT n * 4 = 4
            mystery(n = 0):
                n > 0 = false, this doesn't print anything
                << done with mystery(n = 0)
            << done with mystery(n = 1)
        << done with mystery(n = 2)
    << done with mystery(n = 3)

您可以修改类以打印调用的顺序:

public class MysteryClass {
  static int COUNTER = 0;
  public static void mystery(int n) {
    int callOrder = COUNTER;
    COUNTER++;
     if (n > 0){
        mystery(n-1);
        System.out.println(n * 4 +"  (order: "+callOrder+", n: "+n+")");
        mystery(n-1);
     } else {
       System.out.println("wont print and wont recurse(negative): " +"(order: "+callOrder+", n: "+n+")");
     }
  }
  public static void main(String[] args) {
     MysteryClass.mystery(3);
  }
}

这将打印:

wont print and wont recurse(negative): (order: 3, n: 0)
4  (order: 2, n: 1)
wont print and wont recurse(negative): (order: 4, n: 0)
8  (order: 1, n: 2)
wont print and wont recurse(negative): (order: 6, n: 0)
4  (order: 5, n: 1)
wont print and wont recurse(negative): (order: 7, n: 0)
12  (order: 0, n: 3)
wont print and wont recurse(negative): (order: 10, n: 0)
4  (order: 9, n: 1)
wont print and wont recurse(negative): (order: 11, n: 0)
8  (order: 8, n: 2)
wont print and wont recurse(negative): (order: 13, n: 0)
4  (order: 12, n: 1)
wont print and wont recurse(negative): (order: 14, n: 0)

您可以验证@bgamlath在他的答案中所说的内容是否与发生的事情相符。 order是指调用递归方法的顺序。

您还可以看到对称性,顺序为 0 的调用,中间打印 12,以及上面递归 4、8、4(对称也是(和波纹管的相同结果。如果你从 4 开始,你会看到一个更大的对称性例子,因为之前和之后的递归。

理解递归的诀窍是考虑不同的情况 imo,而不是在精神上跟踪调用图。

您的mystery函数处理两种不同的情况:

  • n =< 0:什么都不做

  • n > 0

    • 做一些递归的事情,n递减,不在乎什么。
    • 打印n * 4
    • 再次执行递归操作。

我们可以看到,这个函数唯一能做的就是打印一些数字。所以对于n == 3我们得到(Maybe print stuff) 12 (Maybe print stuff)

现在,让我们用相同的n == 2调用替换未知的东西,并且我们得到

((Maybe print stuff) 8 (Maybe print stuff)) 12 ((Maybe print stuff) 8 (Maybe print stuff))

如果我们能记住基本情况,即mysteryn == 0我时什么都不做认为调用的结构在未多次扩展时最为明显。您可以继续替换以确保您的答案正确,但是当试图弄清楚时递归函数的作用通常只会伤害我的大脑,试图思考深入了解拨打的确切内容。

最新更新