簡體   English   中英

Java函數中的2個遞歸調用

[英]2 recursive calls in function in Java

我在Java中使用遞歸時遇到了一些問題。 這是我的代碼

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的值?

在沒有副作用的情況下,可以將這種遞歸函數視為常規函數。 您可以繪制一個小表來顯示函數的調用結果,從零開始:

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值的增加,您的函數將花費更長的時間,因為它將重新進行許多已經完成的計算。 幸運的是,這可以通過一個簡單且非常常見的技巧來解決,該技巧稱為備忘錄

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)時),然后將這些值放回樹中。

您的遞歸函數是

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相加以獲得最終結果...

例如,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}
        }
    }
 }
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用於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

請注意,這具有指數級的復雜性。
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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM