public static void main(String[]args){
multiply(2,4);
}
public static int multiply(int a, int b) {
if (b == 0) {
return 0;
}
return a + multiply(a, b - 1);
}
}
我有这个递归声明,我想知道它是如何工作的,这是正确的思考方式吗?
return 2 + (2, 3);
return 2 + (2,2);
return 2 + (2,1);
return 2 + (2,0);
return 2 + 6;
return 2 + 4;
return 2 + 2;
return 2 + 0;
答案 0 :(得分:3)
最简单的方法是尝试:
public static int multiply(int a, int b) {
System.out.println("-->multiply("+a+", "+b+")");
if (b == 0) {
System.out.println("<--returning zero for "+a+"*"+b);
return 0;
}
int ret = a + multiply(a, b - 1);
System.out.println("<--returning "+a+"*"+b+" = "+ret);
return ret;
}
您的输出将是:
-->multiply(2, 4)
-->multiply(2, 3)
-->multiply(2, 2)
-->multiply(2, 1)
-->multiply(2, 0)
<--returning zero for 2*0
<--returning 2*1 = 2
<--returning 2*2 = 4
<--returning 2*3 = 6
<--returning 2*4 = 8
箭头显示堆栈何时增长(-->
)以及何时收缩(<--
)。这是一种有用的技术,通常可视化递归调用:在输入方法后记录输入,并在返回之前记录结果。
答案 1 :(得分:2)
我对你所展示的内容并不十分清楚,虽然它看起来相当正确(如果我正确地解释它)。您需要完成方法的每次调用,直到您遇到基本情况(在本例中,它是b == 0
时)。然后,您可以重新开始工作,替换返回的值。
multiply(2,4)
返回2 + multiply(2,3)
。
multiply(2,3)
返回2 + multiply(2,2)
。
multiply(2,2)
返回2 + multiply(2,1)
。
multiply(2,1)
返回2 + multiply(2,0)
。
multiply(2,0)
会返回0
。
所以,如果我们用返回值替换,从下往上工作,你得到:
return 2 + 2 + 2 + 2 + 0;
等于8
。 2 x 4 = 8
。
答案 2 :(得分:2)
你几乎是完美的,只是......请记住,对于我们这些可怜的人来说,返回似乎对于我们倾向于考虑它们的人来说,要恢复指令的顺序。
因此:
是,在分析嵌套的调用时,您完全正确
NO ,你在分析返回时犯了错误,这是按照以下顺序发生的(与你的感觉相比还原,但如果你考虑返回LAST函数调用,这是有道理的第一):
Returning: 2+0
Returning: 2+2
Returning: 2+4
Returning: 2+6
由于一般解决方案优于特定解决方案,因此以下是您的原始程序,它使用了2个额外的printfs()
和一个额外的变量(res
)。您可以通过这种方式跟踪任何重复。 :-)
public static void main(String[] args){
multiply(2,4);
}
public static int multiply(int a, int b) {
int res;
if (b == 0) {
return 0;
}
System.out.printf("Calling: %d+multiply(%d, %d)\n", a, a, b-1);
res = multiply(a, b - 1);
System.out.printf("Returning: %d+%d\n", a, res);
return a + res;
}