Java遞迴(recursion),java遞迴recursion
人分兩種:男人和女人;演算法分兩種:遞迴的和迭代/迴圈的;遞迴是指用自己的較簡單的情形定義自己。
在數學和電腦科學中,遞迴是一種思路和策略,可以用於術語的定義(什麼是運算式),問題的描述和問題求解。用於問題求解的遞迴稱為遞迴法。
有一個故事。物理學家計算10!時會說,“看,它等於1*2*~*10,即3628800”;數學家則說:“哦,10的階乘,它等於10乘以9!”。
遞迴演算法“輕率地”認為自己的較簡單的情形是已知的。既然fact(n-1)是已知的,因而fact(n) 可求。這樣“輕率”對理解遞迴概念至關重要。遞迴法不直接解決問題,而是將問題變成一個趨向遞迴出口的問題。使用遞迴方法需要存在一個基準情形,以避免無限迴圈(狗追自己的尾巴)。
package algorithm.recursion;public class RecursionDemo{ /** * 遞迴求Fibonacci級數的第n個元素,n基於1的自然數。 */ public static int fibonacc(int n){ if(n<=1) return n; else return fibonacc(n-1)+fibonacc(n-2); } /** * 迭代求Fibonacci級數的第n個元素,n基於1的自然數。 */ public static int fibonacc1(int n){ int first , second ,result ; first =second=result= 1; for(int i=3;i<=n ;i++){ result = first + second; first = second; second =result; } return result; } }大多數情況下,迭代法和遞迴法能夠相互轉化。
使用遞迴法有2條實踐準則:
1、設計優先。在任何情況下都可以採用遞迴法,簡潔而清晰的程式設計優先。某些問題,例如那些需要後退的問題(如找出迷宮的出路、對樹的一些操作),如果不採用遞迴則很難解決。
2、
效率平衡。如果遞迴調用中出現重複性工作,改用迴圈。對於一般的數值計算,遞迴法通常不合適。
Java遞迴方法是通過方法調用棧實現的。在BlueJ中設定斷點運行factorial (5),將顯示方法調用情況。它僅僅“輕率地認為”factorial (4)已知,依此類推。到factorial (5),目前沒有進行任一乘法計算。方法調用棧中有6個棧幀,頂層將計算factorial (0)。遞迴的方法的兩個階段是遞推和迴歸。
例如使用遞迴式sum(n) =n + sum(n-1),yqj2065看見過一個趣題。
static long sum1(long a) { return (a == 1)? 1:(a + sum1(a - 1)); } static long sum2(long a) { return (a == 1)? 1:(sum2(a - 1) + a); }兩者有區別嗎?【註:在Java7時sum1(6000)StackOverflowError,Java8到大約13000才溢出。
原因不明。】
漢諾塔
漢諾塔問題(Hanoi Tower problem):有三根杆子A、B、C,A杆上串有上小下大若干碟子。每次移動一塊碟子,在確保小碟子只能疊在大碟子上面的條件下,利用B過渡,請把所有碟子從A杆移到C杆上。
對於具有遞迴思維的人,再多的碟子,也不過是兩部分:上面的n-1個碟子被看成粘在一起的小碟子,而下面是一個大碟子。漢諾塔問題的遞迴演算法:
結束條件: A杆上只有一個碟子,將它移到C。
遞迴式:
1、將上面的n-1個碟子從出發地A移到中轉站B;
2、將第n個碟子移到目的地C;
3、將n-1個碟子從中轉站B移到目的地C。
package algorithm.recursion;public class HanoiTower{ private static int step= 0; /**漢諾塔的遞迴示範。 * @param from 碟子的出發地 * @param temp 碟子的中轉站 * @param to 碟子的到達地 * @param n 要移動的碟子個數 */ static void hanoi(char from, char temp, char to, int n){ if (n == 1) { step++; System.out.println("第"+step+ "步: "+ from+"→"+ to); }else { //將n-1個碟子移到中轉站,故目前的到達地是temp。 hanoi(from, to,temp,n-1); //第n個碟子移到到達地 step++; System.out.println("第"+step+ "步: "+ from+"→"+ to); //將n-1個碟子移到到達地。 hanoi(temp,from,to,n-1); } }}hanoi(‘A’, ‘B’, ‘C’, 3)的輸出:
第1步: A→C
第2步: A→B
第3步: C→B
第4步: A→C
第5步: B→A
第6步: B→C
第7步: A→C
漢諾塔問題的迭代演算法比較複雜,程式碼程式庫中有參考實現。
練習:
1.Given a non-negative int n, return the sum of its digits recursively (no loops). Note that mod (%) by 10 yields the rightmost digit (126 % 10 is 6), while divide (/) by 10 removes the rightmost digit (126 / 10 is 12).
sumDigits(126) → 9
sumDigits(49) → 13
sumDigits(12) → 3
類似的: 遞迴求一個非負int包含的5的個數。
2.小朋友排排坐,單號伸出2手指,雙號伸出3手指,遞迴求n個小朋友時手指的總數。
sum(0) → 0
sum(1) → 2
sum(2) → 5
Java 遞迴 Recursion
method1函數遞迴調用自己,當遇到普通檔案ff.txt時,會執行“return”語句返回;返回只是返回到上一級method1()調用,並不會退出整個程式。你之所以認為會停下來,是因為你對函數遞迴調用的概念還沒理解。
java解答一題recursion遞迴的問題
public static int divide(int a, int b) {int result = 0;while (a >= b) {result++;a = a - b;}return result; }public static final void main(String[] args) {System.out.println(divide(60, 12));System.out.println(divide(27, 8));}