我遇到了一个问题。当我得到这段代码时,我不明白该怎么想:
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))
如果我们能记住基本情况,即mystery
在n == 0
我时什么都不做认为调用的结构在未多次扩展时最为明显。您可以继续替换以确保您的答案正确,但是当试图弄清楚时递归函数的作用通常只会伤害我的大脑,试图思考深入了解拨打的确切内容。