如何理解遞歸
本質上是將原來的問題轉化爲更小的同樣的問題,問題的規模可以逐漸縮小,通常小到不能再小的時候,會更加容易的解決。
舉一個簡單的例子:數組求和
Sum(arr[0...n-1]) = arr[0]+Sum(arr[1...n-1])
得到一個更小同一問題
求數組中n個數的和,其實等於把索引爲0的數拿出來加上第1到n-1所有元素的和。在這兩個Sum函數中,第二個sum要比第一個更小,因爲第一個sum需要求n個數的和,而第二個只需要對n-1個數求和。
上述過程依次類推Sum(arr[1...n-1]) = arr[1]+Sum(arr[2...n-1])
得到更小統一問題- ······
Sum(arr[n-1...n-1]) = arr[n-1]+Sum(arr[])
最基本的問題
對一個數字求和就等於這個數組加上對空數組求和,空數組的和爲0。
將最基本的問題解決了之後,根據上面所述的一系列邏輯就可以將原問題解決。
使用遞歸解決數組求和
Sum.java
public class Sum {
// 用戶操作的函數
public static int sum(int[] arr) {
// 遞歸的初始調用是從0開始到n-1
return sum(arr, 0);
}
// 計算arr【l...n)這個區間所有數字的和 l-(n-1)的和
// 真正的遞歸的函數
private static int sum(int[] arr, int l) {
// 當左邊界l等於數組長度的時候 即整個數組爲空的時候
if (l == arr.length)
return 0;
return arr[l] + sum(arr, l + 1);
}
// 聲明一個數組進行main函數測試
public static void main(String[] args) {
int[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.out.println(sum(nums));
}
}
測試結果:
55
遞歸算法的基本原則
通過數組求和完成了一個遞歸函數sum()
private static int sum(int[] arr, int l) {
if (l == arr.length)
return 0;
return arr[l] + sum(arr, l + 1); // 讓arr[l] 加更小的一段數組中所有元素的和
}
所有的遞歸算法都是可以分成兩部分:
求解最基本的問題
,這個問題是需要編寫邏輯求解的。通常最基本問題都是非常簡單的。把原問題轉化成更小的問題
,也是遞歸算法最核心的部分。不是簡單的求一個更小的問題的答案,而是根據更小問題的答案構建出原問題的答案。
在寫遞歸函數時一定要注重遞歸函數本身的語意。
對於求和sum來說,它本身就是計算l…n-1之間所有數字的和。(遞歸函數的宏觀語意)遞歸函數本身也是一個函數,完成一個功能。把需要調用的遞歸函數想像成一個子過程,思考子過程如何幫助自己解決問題。