遞歸
程序調用自身的編程技巧稱爲遞歸
public static void show(){
show();
}
它通常把一個大型複雜的問題層層轉化爲一個與原問題相似的規模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重複計算,大大地減少了程序的代碼量。
一般來說,遞歸需要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。
遞歸前進段
邊界條件
遞歸返回段
分治算法
分治算法就是將原問題劃分成n個規模較小,並且結構與原問題相似的子問題,遞歸地解決這些子問題,然後在合併其結果,就得到原問題的解。
分治算法的遞歸實現中,每一層遞歸都會涉及這樣三個操作:
- 分解:將原問題分解成一系列子問題。
- 解決:遞歸地求解各個子問題,若子問題足夠小,則直接求解。
- 合併:將子問題的結果合併成原問題。
分治算法能解決的問題,一般需要滿足下面這幾個條件:
- 原問題與分解成的小問題具有相同的模式
- 原問題分解成的子問題可以獨立求解,子問題之間沒有相關性
- 具有分解終止條件,也就是說,當問題足夠小,可以直接求解
- 可以將子問題合併成原問題,而這個合併操作的複雜度不能太高,否則就起不到減小算法總體複雜度的效果了。
另外:
- 但凡能夠用數學歸納法解決的問題,都可以使用分治思想
- 分治思想不一定使用遞歸結構
範例:前n項求和問題
public class Recursion {
public static void main(String[] args) {
//遞歸累加 O(n)
test01();
//迭代累加 O(n)
test02();
}
private static void test02() {
int sum=0;
int n=100;
for (int i=0;i<=n;i++){
sum+=i;
}
System.out.println(sum);
}
private static void test01() {
int n=100;
int sum=sum(n);
System.out.println(sum);
}
private static int sum(int n) {
if(n==1){
return 1;
}
return sum(n-1)+n;
}
}
執行結果
5050
5050
範例:n的階乘問題
public class Recursion02 {
public static void main(String[] args) {
//遞歸階乘
test01(); //O(n)
//迭代階乘
test02();//O(n)
}
private static void test02() {
int n=10;
int product=1;
for (int i=1;i<=n;i++){
product*=i;
}
System.out.println(product);
}
private static void test01() {
int n=10;
int product=factorial(n);
System.out.println(product);
}
private static int factorial(int n) {
if(n==1){
return 1;
}
return factorial(n-1)*n;
}
}
執行結果
3628800
3628800
範例:斐波那契數列問題
public class Recursion03 {
public static void main(String[] args) {
//遞歸斐波那契數列 O(2^n)
test01();
//迭代斐波那契數列 O(n)
test02();
}
private static void test02() {
int n=45;
int num=getFabonacci(n);
System.out.println(num);
}
private static int getFabonacci(int n) {
if (n==1||n==2){
return 1;
}
int first=1;
int second=1;
int current=0;
for (int i=3;i<=n;i++){
current=first+second;
first=second;
second=current;
}
return current;
}
private static void test01() {
int n=5;
int num=fabonacci(n);
System.out.println(num);
}
private static int fabonacci(int n) {
if (n==1||n==2){
return 1;
}
return fabonacci(n-1)+fabonacci(n-2);
}
}
執行結果
5
1134903170