双递归 - Java

时间:2014-04-23 10:19:04

标签: java recursion

我遇到了问题。当我得到这段代码时,我无法理解如何思考:

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 但我不知道他们是怎么得到的......有人可以解释一下吗?

6 个答案:

答案 0 :(得分:7)

这是函数调用的方式。要了解更多信息,请拿一支铅笔和一张纸,然后了解会发生什么。首先,为神秘而做(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)

答案 1 :(得分:0)

mystery(int n)方法中,您使用

调用自己两次
mystery(n-1);

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

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

答案 2 :(得分:0)

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

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

......你明白了

答案 3 :(得分:0)

您可以修改课程以打印通话顺序:

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指的是对递归方法的调用的顺序。

您还可以看到symetry,订单为0的调用,中间打印12,以及上面和下面的递归4,8,4(对称度)相同的结果。如果从4开始,由于前后递归,你会看到一个更大的对称性例子。

答案 4 :(得分:0)

这很简单!

这就是:

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)

答案 5 :(得分:0)

理解递归的技巧是考虑不同的情况,而不是思想 跟踪调用图。

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

  • n =< 0:什么都不做

  • n > 0

    • 递归递归到n递减,不关心什么。
    • print 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))的相同调用替换未知内容 我们得到

mystery

如果我们能够牢记基本情况,即n == 0我{{1}}时什么都不做 认为当呼叫的结构未多次扩展时,呼叫的结构最为明显。 您可以继续替换以确保您的答案是正确的,但在尝试计算时 一个递归函数它通常只是伤害我的大脑试图思考 非常关于究竟是什么电话。