Java中的2个函数递归调用

时间:2015-05-17 11:23:21

标签: java recursion

我在Java中使用Recursion遇到了一些问题。 这是我的代码

public class recursionTrial {

public static void main(String[] args)
{
System.out.println(doSomething(6));
}

public static int doSomething(int n)
{
    if (n==0 || n==1)
        return 0;

    else
        return n + doSomething(n-1) + doSomething(n-2);


}

}

这给了我38的输出。但是我无法在脑中或纸上追踪递归函数。如何锻炼外观? 6 + 5 ....等等。

如果只是

我就知道了
return n + doSomething(n-1)

那么它将是6 + 5 + 4 + 3 + 2 = 20;这是代码的第二部分令我感到困惑。如果有人可以向我解释如何正确地追踪递归函数并编写工作,我将不胜感激!还有一种方法可以编写一段代码,在每次更改之前打印n的值吗?

5 个答案:

答案 0 :(得分:2)

在没有副作用的情况下,人们可以将这种递归函数视为常规函数。您可以绘制一个小表,显示函数调用的结果,从零开始:

n res computation
- --- -----------
0   0           0
1   0           0
2   2       2+0+0
3   5       3+2+0
4  11       4+5+2
5  21      5+11+5
6  38     6+21+11

第二次递归调用不需要特殊的心理处理:它与第一次递归调用相同。

注意:随着n的值上升,您的函数将逐渐变长,因为它将重新执行已经完成的大量计算。幸运的是,这可以通过一个简单且非常常见的技巧来解决,称为memoization

答案 1 :(得分:0)

doSomething(1)=返回0,

doSomething(2)== 2 + dosomething(1)= 2 + 0 = 2,

doSomething的(3)= 3 + doSomething的(2)= 3 + 2 = 5,

doSomething的(4)= 4 + doSomething的(3)+ doSomething的(2)= 4 + 5 + 2 = 11

doSomething的(5)= 5 + doSomething的(4)+ doSomething的(3)= 5 + 11 + 5 = 21,

doSomething的(6)= 6 + doSomething的(5)+ doSomething的(4)= 6 + 21 + 11 = 38

从doSomething(6)开始,它调用:doSomething(5)去那行,找出doSomething(5)我们需要知道doSomething(4)和doSomething(3)....并按照自己的方式工作在树上,直到你得到一个实际的"返回值"在这种情况下,当我们到达doSomething(1)时,然后将这些值放入树中。

答案 2 :(得分:0)

你的递归函数是

f(n) = n + f(n-2) + f(n-1)

执行流程如下。

    首先评估
  1. f(n-2)...为了计算f(n-2),程序再次对f(n-4)和f(n-3)进行递归调用,依此类推......
  2. 接下来,评估f(n-1)......这又取决于f(n-3)和f(n-2)等的计算值...
  3. 这两个值与n一起添加以获得最终结果......
  4. 例如,n = 4的递归树如下(为简单起见,我没有显示n的加法):

    f(4) {
        f(2) {
            f(0) {0}
            f(1) {0} 
        }
        f(3) {
            f(1) {0}
            f(2) { 
                f(0) {0} 
                f(1) {0}
            }
        }
     }
    

答案 3 :(得分:0)

public static int doSomething(int n) {
    if (n==0 || n==1)
        return 0;
    else
        return n + doSomething(n-1) + doSomething(n-2);
}

你可以尝试递归扩展,这在概念上是程序的作用。

doSomething(6)扩展为6 + doSomething(5) + doSomething(4)

doSomething(5)扩展为5 + doSomething(4) + doSomething(3)

doSomething(4)扩展为4 + doSomething(3) + doSomething(2)

...

简单地下去递归。例如(我使用dS for doSomething):

dS(6) = 6 + dS(5) + dS(4) =

6 + 5 + dS(4) + dS(3) + 4 + dS(3) + dS(2) = 

6 + 5 + 4 + dS(3) + dS(2) + 3 + dS(2) + dS(1) + 4 + 3 + dS(2) + dS(1) + 2 + dS(1) + dS(0) =

6 + 5 + 4 + 3 + dS(2) + dS(1) + 2 + dS(1) + dS(0) + 3 + 2 + dS(1) + dS(0) + 0 + 4 + 3 + 2 + dS(1) + dS(0) + 0 + 2 + 0 + 0 =

6 + 5 + 4 + 3 + 2 + dS(1) + dS(0) + 0 + 2 + 0 + 0 + 3 + 2 + dS(1) + 0 + 0 + 4 + 3 + 2 + 0 + 0 + 0 + 2 + 0 + 0 =

6 + 5 + 4 + 3 + 2 + 0 + 0 + 0 + 2 + 0 + 0 + 3 + 2 + 0 + 0 + 0 + 4 + 3 + 2 + 0 + 0 + 0 + 2 + 0 + 0 =

38 <-- Final result

答案 4 :(得分:0)

请注意,这具有指数级复杂性 doSomething(6)来电doSomething(5)doSomething(4) doSomething(5)来电doSomething(4)doSomething(3) doSomething(4)来电doSomething(3)doSomething(2) doSomething(3)来电doSomething(2)doSomething(1) doSomething(2)来电doSomething(1)doSomething(0) doSomething(1)为0 doSomething(0)为0

这说明了doSomething()的来电,它们不是结果,因为您为每次通话添加了n

                      6
               _______|_______
              /               \
             5                 4
         ____|____            _|_
        /         \          /   \
       4           3        3     2
      _|_          |        |     |
     /   \        / \      / \   / \
    3     2      2   1    2   1 1   0
   / \   / \    / \      / \
  2   1 1   0  1   0    1   0
 / \  
1   0