遞歸

遞歸是什麼

定義:程序調用自身的編程技巧稱爲遞歸–百度詞條.
首先我們思考一下1+2+3….+100=?要怎麼寫程序來計算呢?
1. 很多人第一反應來使用for循環
2. 利用公式
3. 使用遞歸

public int sum(int n) {
    if(n == 1) {
        return 1;
    }
    return n + sum(n - 1);
}

通過初體驗對比,不難發現以下遞歸有以下幾個特點:
1. 優點:使程序結構更清晰,更簡潔,更容易讓人理解,遞歸要有出口,不然成了死循環.
2. 缺點:使用遞歸調用時,如果過多的調用容易造成java.lang.StackOverflowError即棧溢出和程序執行過慢。這是一個潛在Bug和影響程序執行效率問題,需要謹慎使用。

對於互聯網這種以速度和效率來維護用戶量,建議直接找本文章的遞歸出口.但既然看到了這裏,不妨鍛鍊下自己的思維.

遞歸的執行順序

遞歸函數分爲調用和回退階段,遞歸的回退順序是它調用順序的逆序.說起來比較拗口舉個例子就明白了,在此也明顯的可以看出,遞歸是選擇結構:
這裏寫圖片描述

遞歸執行代碼

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

它的調用順序是
這裏寫圖片描述

遞歸算法實例

有一對兔子,從出生後第3個月起每個月都生一對兔子, 小兔子長到第四個月後每個月又生一對兔子, 假如兔子都不死,問每個月的兔子總數爲多少對?

分析,這個題目是著名的斐波那契數列:1,1,2,3,5,8,13,21….=Sn = Sn-1+Sn-2

規律是:從第三個數開始,每個數都是前兩個數的合.

public static int recursion(int n) {
    if(n == 1 || n == 2) {
        return 1;
    }

    return recursion(n - 1) + recursion(n - 2);
}

遞歸逆序排列字符單詞,例:I Love Java—>Java Love I

public String reverse(String s) {
    int i = s.indexOf("");
    if(s == null || i == -1) {
        return s;
    }
    return reverse(s.substring(i + 1)) + " " + s.substring(0, i);//每次截取第一個單詞放在最後拼接
}

實現二分查找算法. 二分查找,不斷將數組進行對半分割,每次拿中間元素和goal進行比較(前提是數組元素的排序應該是遞增或者遞減)

public static int recursion(int [] arr,int low,int high,int value){
    if(low>high){
        return -1;
    }

    int mid=(low+high)/2;//求中間的值

    if(value==arr[mid]){//如果相等,則找到該值,直接返回
        return mid;
    } else if(value<arr[mid]) {//如果要找的值在中間值得左邊,則下一次遞歸開始的右指針指向該次中間值-1
        return recursion(arr,low,mid-1,value);
    } else {////如果要找的值在中間值得右邊,則下一次遞歸開始的左指針指向該次中間值+1
        return recursion(arr,mid+1,high,value);
    }
}

轉載自

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章