簡體   English   中英

使用Java中的遞歸的因子

[英]Factorial using Recursion in Java

我正在使用Java:The Complete Reference這本書學習Java。 目前我正在研究Recursion主題。

請注意: stackoverflow上有類似的問題。 我搜索了他們,但我沒有找到我的問題的解決方案。 我對以下程序中的邏輯感到困惑。

如果我運行以下程序,它會產生正確的輸出,但我不明白邏輯。

  • 我不理解以下行中的邏輯: result = fact(n-1)* n;
  • 據我所知,如果我們傳遞n = 4的值,如下面的程序所示,
  • 然后,將3 * 4存儲在結果中,即12。
  • 再次,事實(n-1)被稱為。 然后n變為3。
  • 然后將2 * 3存儲在結果中,替換之前的12。
  • 我想你明白我被困在哪里/困惑。

  • 謝謝。

 class Calculation { int fact(int n) { int result; if(n==1) return 1; result = fact(n-1) * n; return result; } } public class Factorial { public static void main(String args[]) { Calculation obj_one = new Calculation(); int a = obj_one.fact(4); System.out.println("The factorial of the number is : " + a); } } 

首先,您應該了解因子是如何工作的。

讓我們4! 舉個例子。

4! = 4 * 3 * 2 * 1 = 24

讓我們使用上面的例子模擬代碼:

int fact(int n)
    {
        int result;
       if(n==0 || n==1)
         return 1;

       result = fact(n-1) * n;
       return result;
    }

在大多數編程語言中,我們有所謂的function stack 它就像一副牌,每張牌都放在另一張牌之上 - 每張牌都可以被認為是一種功能所以,傳遞方法的fact

堆棧級別1: fact(4) // n = 4 and is not equal to 1. So we call fact(n-1)*n

堆棧等級2: fact(3)

堆棧級別3: fact(2)

堆棧級別4: fact(1) //現在,n = 1.所以我們從這個函數返回1。

返回值...

堆棧級別3: 2 * fact(1) = 2 * 1 = 2

堆棧級別2: 3 * fact(2) = 3 * 2 = 6

堆棧級別1: 4 * fact(3) = 4 * 6 = 24

所以我們得到24

請注意以下幾點:

result = fact(n-1) * n;
           return result;

或者干脆:

return fact(n-1) * n;

這會調用函數本身。 以4為例,

根據功能堆棧順序..

return fact(3) * 4;
return fact(2) * 3 * 4
return fact(1) * 2 * 3 * 4

替換結果......

return 1 * 2 * 3 * 4 = return 24

我希望你明白這一點。

這是對使用遞歸因子計算如何工作的另一種解釋。

讓我們稍微修改一下源代碼:

int factorial(int n) {
      if (n <= 1)
            return 1;
      else
            return n * factorial(n - 1);
}

這是3的計算 詳情:

在此輸入圖像描述

來源: RECURSION(Java,C ++)| 算法和數據結構

resultfact方法的局部變量。 因此,每次調用事實方法時,結果都存儲在與先前事實調用不同的變量中。

因此,當使用3作為參數調用fact時,您可以想象它的結果是

 result3 = fact(2) * 3
 result3 = result2 * 3
 result3 = 1 * 2 * 3

我相信,你的困惑來自於你認為只有一個result變量,而實際上每個函數調用都有一個result變量。 因此,舊的結果不會被替換,而是返回。

詳細說明:

int fact(int n)
{
    int result;

   if(n==1)
     return 1;

   result = fact(n-1) * n;
   return result;
}

假設調用fact(2)

int result;
if ( n == 1 ) // false, go to next statement
result = fact(1) * 2; // calls fact(1):
|    
|fact(1)
|    int result;  //different variable
|    if ( n == 1 )  // true
|        return 1;  // this will return 1, i.e. call to fact(1) is 1
result = 1 * 2; // because fact(1) = 1
return 2;

希望現在更清楚了。

public class Factorial {

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

    private static long factorial(int i) {

        if(i<0)  throw new IllegalArgumentException("x must be >= 0"); 
        return i==0||i==1? 1:i*factorial(i-1);
    }
}

會發生什么是遞歸調用本身會導致進一步的遞歸行為。 如果你要寫出來,你會得到:

 fact(4)
 fact(3) * 4;
 (fact(2) * 3) * 4;
 ((fact(1) * 2) * 3) * 4;
 ((1 * 2) * 3) * 4;

你在這里遺漏的關鍵點是變量“result”是一個堆棧變量,因此它不會被“替換”。 詳細說明,每次調用事實時,在解釋器內部創建一個名為“result”的NEW變量,並將其鏈接到方法的調用。 這與鏈接到對象實例而不是特定方法調用的對象字段形成對比

雖然這已經過時了,但谷歌仍然會很好。 所以我想我會提到這一點。 沒有人提到在x = 0時檢查。

0! 和1! 兩者= 1。

如果運行了fact(0),則不會使用之前的答案檢查,並且會導致堆棧溢出。 無論如何簡單修復:

public static int fact(int x){
    if (x==1 | x==0)
        return 1;
    return fact(x-1) * x;
}// fact

使用三元運算符的遞歸解決方案。

public static int fac(int n) {
    return (n < 1) ? 1 : n*fac(n-1);
}

要理解它,你必須以最簡單的方式聲明方法,並且martynas在5月6日發布了它:

int fact(int n) {
    if(n==0) return 1;
    else return n * fact(n-1);
}

閱讀上面的實現,你會明白的。

在我看來,這是初學者對java知識的看法,我建議將n == 1更改為n <= 1或(n == 0)||(n == 1)因為0的階乘是1。

正確的是:

int factorial(int n)
{
    if(n==0||n==1)
        return 1;
    else 
        return n*factorial(n-1);
}

對於因子0,這將返回1.它是否相信我。 我很難學到這一點。 只是因為沒有保持0的條件無法清除面試。

恕我直言,了解與遞歸相關的行動的關鍵是:

  1. 首先,我們深入到棧遞歸,並與每一個電話我們以某種方式修改值(例如,N-1 func(n-1); ),它決定了遞歸是否應該去越陷越深。
  2. 一旦滿足recursionStopCondition(例如n == 0 ),遞歸就會停止,並且方法會執行實際工作並將值返回到上層堆棧中的調用方法,從而冒泡到堆棧頂部。
  3. 捕獲從更深堆棧返回的值非常重要,以某種方式修改它(在您的情況下乘以n),然后將此修改后的值返回到堆棧頂部。 常見的錯誤是來自最深堆棧幀的值直接返回到堆棧頂部,因此忽略所有方法調用。

當然,方法可以在潛入(從堆棧的頂部到底部)或返回途中進行有用的工作。

使用Java 8及更高版本,使用遞歸本身

  UnaryOperator<Long> fact = num -> num<1 ? 1 : num * this.fact.apply(num-1);

並使用它

  fact.apply(5); // prints 120

在內部,它計算如下

5*(4*(3*(2*(1*(1)))))
import java.util.Scanner;

public class Factorial {
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        int n; 
        System.out.println("Enter number: ");
        n = keyboard.nextInt();
        int number = calculatefactorial(n);
        System.out.println("Factorial: " +number);
    }
    public static int calculatefactorial(int n){
        int factorialnumbers=1;
        while(n>0){
         factorialnumbers=(int)(factorialnumbers*n--);   
        }
        return factorialnumbers;
    }
}
public class Factorial2 {
    public static long factorial(long x) {
        if (x < 0) 
            throw new IllegalArgumentException("x must be >= 0");
        if (x <= 1) 
            return 1;  // Stop recursing here
        else 
           return x * factorial(x-1);  // Recurse by calling ourselves
    }
}
public class Factorial {
public static void main(String[] args) {
   int n = 7;
   int result = 1;
   for (int i = 1; i <= n; i++) {
       result = result * i;
   }
   System.out.println("The factorial of 7 is " + result);
}
}

變量“result”是一個局部變量。 當從“main”方法調用fact()方法時,變量“result”存儲在不同的變量中。

Also line : result = fact(n-1) * n; 

這里的邏輯是使用遞歸找到階乘。 java中的遞歸是一個方法調用自身的過程。

同時,您可以使用遞歸在數字的階乘上引用資源。

暫無
暫無

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

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