日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java递归基础

發(fā)布時間:2023/12/3 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java递归基础 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
對于那些不知道遞歸是什么的人(并且像個笑聲一樣),請單擊以下鏈接:Google搜索:遞歸,然后單擊“您的意思是……”項。

希望您終于弄清楚了遞歸是指其自身的任何內(nèi)容(如果不是,那么您可能會永遠(yuǎn)瀏覽Google并試圖找出遞歸是什么!)。 遞歸的一個相當(dāng)常見的例子是斐波那契數(shù)。 斐波納契數(shù)的模式是將前兩個項與下一個項相加,從一個和一個開始。

以下是斐波那契數(shù)的遞歸關(guān)系:

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

遞歸關(guān)系是原始函數(shù)引用自身的任何關(guān)系。 那么我們?nèi)绾握业紽(5)?

F(5)= F(4)+ F(3)
F(5)= [F(3)+ F(2)] + [F(2)+ F(1)] F(5)= [F(2)+ F(1)] +1 +1 +1
F(5)= 1 + 1 + 1 + 1 + 1 F(5)= 5

似乎需要很多工作? 好吧,對于計算機(jī)來說,大多數(shù)時候都相當(dāng)快。 稍后,我將向您介紹動態(tài)編程,因此當(dāng)您要計算較大的斐波那契數(shù)時,我們可以加快速度。

那么遞歸函數(shù)的所有部分是什么? 首先,什么是遞歸函數(shù)? 遞歸函數(shù)是任何直接(間接或間接)調(diào)用自身的函數(shù)。 這是Java中的一個簡單示例:

public static void doIt() {doIt(); }

當(dāng)然,這最終會導(dǎo)致堆棧溢出錯誤,因此不建議您嘗試使用此代碼。

所有有用的遞歸函數(shù)都具有以下一般屬性:減少問題,直到計算機(jī)可以輕松解決為止。 為此,遞歸函數(shù)必須具有:

  • 定義了基本案例(解決方案顯而易見且無法進(jìn)一步簡化的案例)
  • 減少步驟(簡化給定問題的地方)
  • 遞歸調(diào)用自身(基本上解決了更簡單的情況)
  • 在上面的Fibonacci遞歸函數(shù)中,您可以看到它一直在遞歸,直到只加1。 這是因為在斐波那契數(shù)列中1是基本情況,因此我們僅需將1加幾次才能得到F(n)。

    從理論上講,所有遞歸函數(shù)都可以迭代編寫,并且所有迭代函數(shù)都可以遞歸編寫。 但是,在實踐中,您會發(fā)現(xiàn)根據(jù)情況的不同,其中一種或兩種理念會更好地發(fā)揮作用。

    讓我們遞歸地查看階乘函數(shù),并將其與它的迭代親戚進(jìn)行比較。

    階乘(N)= 1 * 2 * 3 * ... * N
    基本上,將1到N的所有整數(shù)相乘即可得到N的階乘。

    迭代實現(xiàn),您的代碼將如下所示:

    public static int iterativeFactorial(int n) {int answer = 1;for (int i = 1; i < n; i++){answer *= i;}return answer; }

    我們還可以編寫此函數(shù)的遞歸等效項:F(1)= 1 F(N)= F(N-1)* N您能看到這如何產(chǎn)生與迭代階乘相同的結(jié)果嗎? 這是遞歸計算階乘的代碼:

    public static int recursiveFactorial(int n) {if (n == 1){return 1;}else{return n * recursiveFactorial(n-1);} }

    那么,就性能而言,遞歸如何與此處的迭代解決方案相提并論? 可悲的是,答案很差。 此處的遞歸函數(shù)需要大量內(nèi)存來存儲方法堆棧并跟蹤每個遞歸調(diào)用中的所有變量,而迭代解決方案僅需跟蹤當(dāng)前狀態(tài)。 那么,為什么還要煩惱遞歸呢? 因為很多時候正確使用遞歸,其性能可能會超過迭代解決方案的性能,并且遞歸函數(shù)也可能更易于編寫(有時)。

    動態(tài)編程

    動態(tài)編程是遞歸的一種形式,但是它是迭代實現(xiàn)的。 還記得我們上面的斐波那契計算機(jī)嗎? F(5)= F(2)+ F(1)+ F(2)+ F(2)+ F(1)F(5)= 3 * F(2)+ 2 * F(1)我們有這里有一些“過度計算”。 只需計算一次F(2)和一次F(1)。 在這種情況下,計算這幾個項并不需要太多的計算工作,但是在某些情況下,幾乎不可能數(shù)百次重新計算解決方案。 因此,我們無需重新計算,而是將答案存儲了下來。

    public static int dynamicFibonacci(int n) {int[] prevSolutions = new int[n];if (n == 1 || n == 2){return 1;}prevSolutions[0] = 1;prevSolutions[1] = 1;for (int i = 2; i < prevSolutions.length; i++){prevSolutions[i] = prevSolutions[i-1] + prevSolutions[i-2];}return prevSolutions[n-1]; }

    因此,再次取F(5)。 如果我們以遞歸的方式進(jìn)行操作,那么將有8次調(diào)用recursiveFibonacci。 但是,這里我們只計算一次F(1),F(2),F(3),F(4)和F(5)。 減少3個電話獲得的收益似乎并不多,但是如果我們嘗試計算F(50)怎么辦? dynamicFibonacci僅會計算50個數(shù)字,但遞歸Fibonacci可能會超過1000個(當(dāng)然,我還沒有計算,所以我不知道它是否超過1000個)。

    關(guān)于動態(tài)編程的最后一點是,它僅在有大量重疊的情況下才有用。 還記得recursiveFactorial函數(shù)嗎? 如果我們調(diào)用recursiveFactorial(50)和dynamicFactorial(50),則它們將花費(fèi)大致相同的時間,因為我們要進(jìn)行相同數(shù)量的計算。 這是因為從來沒有重疊。 這也是為什么排序算法不是通過動態(tài)編程實現(xiàn)的較差選擇的原因:如果您分析大多數(shù)排序算法,則它們幾乎沒有重疊的解決方案,因此對于動態(tài)編程來說是一個較差的選擇。

    這是有關(guān)遞歸和動態(tài)編程的一些問題:

  • 實現(xiàn)recursiveFactorial方法(您以為我忘了把它放在那里)
  • 對于給定的遞歸關(guān)系,編寫一個遞歸方法,將找到F(N)
  • 這種遞歸關(guān)系在迭代方面意味著什么? 為此問題寫一個迭代的解決方案。
  • 這種遞歸關(guān)系是否適合動態(tài)編程? 為什么/為什么不呢?
  • 有比迭代或遞歸解決方案更好的方法來解決此問題嗎? 這是什么(如果有)? 提示:想想卡爾高斯
  • 對于問題2-5,請使用以下遞歸關(guān)系:
    F(1)= 1
    F(N)= F(N-1)+ N

    答案來了……

    參考: Java編程論壇上 JCG合作伙伴的 遞歸

    相關(guān)文章 :

    • Java Micro-Benchmarking:如何編寫正確的基準(zhǔn)
    • 首先記錄異常的根本原因
    • 編程反模式
    • 您不想錯過的十大Java書籍
    • Java日志混亂
    • 做短,但做對!

    翻譯自: https://www.javacodegeeks.com/2011/12/java-recursion-basics.html

    總結(jié)

    以上是生活随笔為你收集整理的Java递归基础的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。