递归_三要素_基础算法必备
遞歸_三要素_基礎算法必備
目錄
第一要素:明確函數作用
第二要素:遞歸結束條件
第三要素:函數等價關系
第一要素:明確函數作用
對于遞歸,我覺得很重要的一個事就是,這個函數的功能是什么,他要完成什么樣的一件事,而這個,是完全由你自己來定義的。也就是說,我們先不管函數里面的代碼什么,而是要先明白,你這個函數是要用來干什么。
// 算 n 的階乘(假設n不為0) public static int f(int n){}這個函數的功能是算 n 的階乘。我們已經定義了一個函數,并且定義了它的功能是什么,接下來我們看第二要素。
第二要素:遞歸結束條件
所謂遞歸,就是會在函數內部代碼中,調用這個函數本身,所以,我們必須要找出遞歸的結束條件,不然的話,會一直調用自己,進入無底洞。也就是說,我們需要找出當參數為啥時,遞歸結束,之后直接把結果返回,請注意,這個時候我們必須能根據這個參數的值,能夠直接知道函數的結果是什么。
例如,上面那個例子,當 n = 1 時,那你應該能夠直接知道 f(n) 是啥吧?此時,f(1) = 1。完善我們函數內部的代碼,把第二要素加進代碼里面,如下
// 算 n 的階乘(假設n不為0) public static int f(int n){if(n == 1){return 1;} }有人可能會說,當 n = 2 時,那我們可以直接知道 f(n) 等于多少啊,那我可以把 n = 2 作為遞歸的結束條件嗎?
當然可以,只要你覺得參數是什么時,你能夠直接知道函數的結果,那么你就可以把這個參數作為結束的條件,所以下面這段代碼也是可以的。
// 算 n 的階乘(假設n>=2) public static int f(int n){if(n == 2){return 2;} }注意我代碼里面寫的注釋,假設 n >= 2,因為如果 n = 1時,會被漏掉,當 n <= 2時,f(n) = n,所以為了更加嚴謹,我們可以寫成這樣:?
// 算 n 的階乘(假設n不為0) public static int f(int n){if(n <= 2){return n;} }第三要素:函數等價關系
第三要素就是,我們要不斷縮小參數的范圍,縮小之后,我們可以通過一些輔助的變量或者操作,使原函數的結果不變。
例如,f(n) 這個范圍比較大,我們可以讓 f(n) = n * f(n-1)。這樣,范圍就由 n 變成了 n-1 了,范圍變小了,并且為了原函數f(n) 不變,我們需要讓 f(n-1) 乘以n。
說白了,就是要找到原函數的一個等價關系式,
f(n) 的等價關系式為 n * f(n-1),
即:f(n) = n * f(n-1)。
這個等價關系式的尋找,可以說是最難的一步了,如果你不大懂也沒關系,因為你不是天才,你還需要多接觸幾道題,我會在接下來的文章中,找 10 道遞歸題,讓你慢慢熟悉起來。?
找出了這個等價,繼續完善我們的代碼,我們把這個等價式寫進函數里。如下:
// 算 n 的階乘(假設n不為0) public static int f(int n){if(n <= 2){return n;}// 把 f(n) 的等價操作寫進去return f(n-1) * n; }?至此,遞歸三要素已經都寫進代碼里了,所以這個 f(n) 功能的內部代碼我們已經寫好了。
這就是遞歸最重要的三要素,每次做遞歸的時候,你就強迫自己試著去尋找這三個要素。
測試一下這個【階乘】:【15就接近int最大值了】
package test; /*** * @author laoshifu* 2021年12月8日*/ public class Action {public static void main(String[] args) {long start = System.currentTimeMillis();System.out.println(f(15));long end = System.currentTimeMillis();System.out.println("消耗時間:"+(end-start));}// 算 n 的階乘(假設n不為0)public static int f(int n){if(n <= 2){return n;}// 把 f(n) 的等價操作寫進去return f(n-1) * n;} }希望能對大家有所幫助。?
總結
以上是生活随笔為你收集整理的递归_三要素_基础算法必备的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java_斐波那契数列_兔子生兔子算法
- 下一篇: 【实施工程师】Wampserver64橙