一:什么是遞歸算法?
遞歸算法就是直接或者間接的調(diào)用自己的方法,在達(dá)到一個條件的時候停止調(diào)用(遞歸出口),所以一定要找準(zhǔn)好條件,讓遞歸停止,否則就會是無限進(jìn)行下去
二:遞歸程序設(shè)計(jì)的關(guān)鍵
1:找出調(diào)用中所需要的參數(shù)
2:返回的結(jié)果
3:遞歸調(diào)用結(jié)束的條件
三:遞歸程序注意
1:要有方法中自己調(diào)用自己
2:要有分支結(jié)構(gòu)
3:要有結(jié)束的條件
四:簡單敘述遞歸函數(shù)的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1:簡潔清晰,實(shí)現(xiàn)容易,可讀性好
2:在遍歷的算法中,遞歸比循環(huán)更為簡單
缺點(diǎn):
1:效率低,使用遞歸函數(shù)是有空間和時間的消耗的。并且很多計(jì)算都是重復(fù)的,對性能有較大的影響
2:可能導(dǎo)致調(diào)用棧的溢出,每一次函數(shù)調(diào)用,在內(nèi)存棧中分配空間,而每一個棧的容量是有限的,當(dāng)遞歸的層級太多的時候,超出棧的容量,就會導(dǎo)致棧溢出。
3:遞歸函數(shù)需要系統(tǒng)的堆棧,空間消耗比非遞歸的要消耗很多,并且深度太大的話,系統(tǒng)可能會支撐不住
五:注意
a.簡單的用循環(huán),復(fù)雜的用遞歸(可以實(shí)現(xiàn)大部分相關(guān)問題)
b.有規(guī)律的問題,循環(huán)不方便時,使用遞歸是不錯的建議。
c.循環(huán)方法比遞歸方法快,避免了一系列函數(shù)的調(diào)用,返回中涉及參數(shù)傳遞,返回值的額外開銷,每遞歸一次,棧內(nèi)存就多占用一截
d.能用循環(huán),就盡量不要用遞歸.......
e.當(dāng)遞歸中出現(xiàn)分支結(jié)構(gòu)的時候(可以出現(xiàn)多個分支),注意每一個分支結(jié)構(gòu)都要有結(jié)束條件。
f.只要函數(shù)調(diào)用了自己,不論間接或者直接,都算遞歸。
g.非遞歸函數(shù)效率高,但是較難編程,可讀性較差
六:相關(guān)遞歸問題
1: 斐波那契數(shù)列
for循環(huán):
1 import java.util.Scanner; 2 public class Day1{ 3 public static void main(String[] args){ 4 System.out.println("請輸入位數(shù)所顯示的數(shù)字:"); 5 Scanner sc = new Scanner(System.in); 6 int x = sc.nextInt(); 7 int x1 = 1; 8 int x2 = 1; 9 int x3 = 0;10 int add = 2;11 System.out.printf("數(shù)列分別為:\n1\t1\t");12 for(int i = 1;i<=x-2;i )13 {14 //因?yàn)榍皟身?xiàng)是一樣的,從第三項(xiàng)開始出現(xiàn)不同的數(shù)字,所以進(jìn)行減二15 //所定義了三個變量,x1代表第一個數(shù)字,x2代表第二個數(shù)字,x3代表第一個數(shù)字與第二個數(shù)字的和,所賦予他們的意義不要改變16 x3 = x1 x2;17 add = add x3;18 x1 = x2;19 x2 = x3;20 System.out.printf("%d\t",x3);21 }22 System.out.println("\n第" x "項(xiàng)數(shù)字為:" x3);23 System.out.println("前" x "項(xiàng)和為:" add);24 }25 }
遞歸算法:
1 public class Day1{ 2 public static int f(int n){ 3 if(n==1||n==2){ 4 return 1; 5 }else{ 6 return f(n-1) f(n-2); 7 } 8 } 9 public static void main(String[] args){10 System.out.println(f(5));11 }12 }
想法:
遞歸算法對于一些問題來說是真的簡單,斐波那契數(shù)列的公式:fn = f(n-1) f(n - 2) (n >= 2),考慮前兩個數(shù)字的話,就是1,由于從0開始,可以理解為
F0 = 0; F1 = 1; F1 = 1;正好是與計(jì)算機(jī)相對應(yīng)
2: 0-100數(shù)字進(jìn)行相加
for循環(huán):
1 public class Day1{2 public static void main(String[] args){3 int add = 0;4 for(int i = 0;i <= 100;i ){5 add = add i;6 }7 System.out.println("0-100的和為:" add);8 }9 }
遞歸算法:
1 public class Day1{ 2 public static int f(int n){ 3 if(n>0) 4 return n f(n-1); 5 return 0; 6 }//盡量有一個臨界的點(diǎn),if(n == 1)return 1;else return n f(n-1); 7 public static void main(String[] args){ 8 System.out.println("0-100的和為:" f(100)); 9 }10 }
3:八皇后
摘自百度百科,注釋比較明細(xì):
1 public class Day1 { 2 private int[] column; //同欄是否有皇后,1表示有 3 private int[] rup; //右上至左下是否有皇后 4 private int[] lup; //左上至右下是否有皇后 5 private int[] queen; //解答 6 private int num; //解答編號 7 8 public Day1() { 9 column = new int[8 1];10 rup = new int[(2*8) 1];11 lup = new int[(2*8) 1];12 for (int i = 1; i <= 8; i )13 column[i] = 0;14 for (int i = 1; i <= (2*8); i )15 rup[i] = lup[i] = 0; //初始定義全部無皇后16 queen = new int[8 1];17 }18 19 public void backtrack(int i) {20 if (i > 8) {21 showAnswer();22 } else {23 for (int j = 1; j <= 8; j ) {24 if ((column[j] == 0) && (rup[i j] == 0) && (lup[i-j 8] == 0)) {25 //若無皇后26 queen[i] = j; //設(shè)定為占用27 column[j] = rup[i j] = lup[i-j 8] = 1;28 backtrack(i 1); //循環(huán)調(diào)用29 column[j] = rup[i j] = lup[i-j 8] = 0;30 }31 }32 }33 }34 35 protected void showAnswer() {36 num ;37 System.out.println("\n解答" num);38 for (int y = 1; y <= 8; y ) {39 for (int x = 1; x <= 8; x ) {40 if(queen[y]==x) {41 System.out.print("Q");42 } else {43 System.out.print(".");44 }45 }46 System.out.println();47 }48 }49 50 public static void main(String[] args) {51 Day1 queen = new Day1();52 queen.backtrack(1);53 }54 }
漢諾塔問題:
稍后繼續(xù)編輯,由于零散時間寫的博客,過兩三天就會補(bǔ)齊
七:總結(jié)
貴在堅(jiān)持吧,最近被些事情忙懷了,毫不夸張的說,感覺生活下去的勇氣都是斷斷續(xù)續(xù)的,有朋友不斷的鼓勵我,天將降大任于斯人也,必須苦其心志,勞其筋骨。
說句最現(xiàn)實(shí)的話,努力了真的是不一定成功,真的是需要一定的機(jī)遇的,但是努力的目的是什么?就是當(dāng)機(jī)遇降臨到你的身上的時候,你是否能抗的住它呢?努力就會給你力量!
加油!要走出屬于自己的道路來!
來源:http://www.icode9.com/content-1-127501.html