遞歸運用實例
課後作業1
一.使用組合數公式利用n!來計算
1.程序設計思想
①提示用戶輸入n和k的值。
②判斷n是否類型正確,若不正確結束程序。
③判斷k是否類型正確,若不正確結束程序。
④判斷n是否大於等於k,若是,繼續運行程序,否則結束程序。
⑤調用計算階乘的方法,在此方法中,若輸入的數字為0或1,返回1;若不是,則用遞歸的方法重復調用此方法計算階乘。
2.程序流程圖
3.程序源代碼
import java.util.Scanner; import java.math.BigInteger; public class CombinatorialNumber1 { /** * @paramargs */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("求n!/(k!*(n-k)!),請輸入n和k:");//提示用戶輸入n和k Scanner input=new Scanner(System.in); int n=0,k=0; if(input.hasNextInt())//判斷n是否是整型 { n=input.nextInt();//輸入n的值 } else//n輸入的不是整型,報錯並結束程序 { System.out.println("您輸入的數據有錯!"); System.exit(0); } if(input.hasNextInt())//判斷k是否是整型 { k=input.nextInt();//輸入k的值 }else//n輸入的不是整型,報錯並結束程序 { System.out.println("您輸入的數據有錯!"); System.exit(0); } if(n>=k)//因要求(n-k)!,所以需要判斷n>=k是否成立 { //調用方法分別計算n!、k!、(n-k)!,計算最後結果並輸出 System.out.print(n+"!/("+k+"!*("+n+"-"+k+")!))="+calculateN(n).divide((calculateN(k).multiply(calculateN(n-k))))); } else//n<k,無法計算,報錯並結束程序 { System.out.println("您輸入的數據有錯!"); System.exit(0); } } public static BigInteger calculateN(int n) //計算n! { if(n==1||n==0)//判斷h是否為1或0,若是,則無需進行遞歸,其階乘為1 { return BigInteger.valueOf(1); } return BigInteger.valueOf(n).multiply(calculateN(n-1));//遞歸調用calculateN方法 } }
4.結果截圖
5.實驗總結
本題中出現的問題主要是對於BigInteger的使用不熟練,在int型時返回1,而在BigInteger中要用BigInteger.valueOf(1);在BigInteger中的加減乘除需調用對應的函數來實現,而在普通的則用對應的符號就可以。
二. 使用遞推的方法用楊輝三角形計算
1.程序設計思想
①提示用戶輸入組合數的n和k。
②判斷n和k是否合法,若不合法,則結束程序;合法,繼續程序。
③定義一個(n+1)*(n+1)的二維數組用來放楊輝三角的數值。
④利用循環嵌套完成楊輝三角中每個位置數值的計算。先為每一行賦值,每行的第一個數和最後一個數均為1,其余位置為上一行的第k-1和k個數的和,然後為下一行賦值。
⑤輸出指定位置的數值。
2.程序流程圖
3.程序源代碼
import java.util.Scanner; public class YanguiTriangle { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Scanner input=new Scanner(System.in); int n=0; int k=0; System.out.println("請輸入組合數C_n^k的n和k:");//提示用戶輸入n和k if(input.hasNextInt())//判斷類型是否正確 { n=input.nextInt();//類型正確輸入n } else//類型不正確報錯並結束程序 { System.out.println("輸入錯誤!"); System.exit(0); } if(input.hasNextInt())//判斷類型是否正確 { k=input.nextInt();//類型正確輸入k } else//類型不正確報錯並結束程序 { System.out.println("輸入錯誤!"); System.exit(0); } if(n>0&&k>=0&&n>=k)//判斷n和k的值是否合法且n>=k是否成立 { int triangle[][]=new int[n+1][n+1];//定義n+*n+1的數組存放楊輝三角各位置的 for(int i=0;i<=n;i++) { for(int j=0;j<=i;j++) { if(j==0)//每行第一個元素為1 { triangle[i][j]=1; } else if(i==j)//每行最後一個元素為1 { triangle[i][j]=1; } else//為其余位置元素賦值 { triangle[i][j]=triangle[i-1][j-1]+triangle[i-1][j]; } } } System.out.println("結果為:"+triangle[n][k]);//顯示用戶指定位置的元素的值 } } }
4.結果截圖
5.實驗總結
本題的問題出現在定義二維數組上,開始想讓用戶自己輸入楊輝三角的高度,後來覺得可能會造成空間的浪費。經過思考,發現可以在用戶輸入n和k的值後,定義生成n+1*n+1的二維數組,這樣造成的浪費會少一點。還有在此程序中需特別註意數組的下標不要弄混。
三.使用遞歸的方法用組合數遞推公式計算
1.程序設計思想
①提示用戶輸入組合數中n和k的值。
②判斷n和k是否合法,若不合法,則結束程序;合法,繼續程序。
③定義計算組合數的方法。如果輸入的k=0或n,則 =1;如果k=1,則其他情況則根據公式 計算。
④輸出結果並結束程序。
2.程序流程圖
3.程序源代碼
import java.util.Scanner; public class CombinatorialNumber3 { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("請輸入組合數C_n^k中的n和k:");//提示用戶輸入n和k Scanner input=new Scanner(System.in); int n=0,k=0; if(input.hasNextInt())//判斷類型是否正確 { n=input.nextInt();//類型正確輸入n } else//類型不正確報錯並結束程序 { System.out.println("輸入錯誤!"); System.exit(0); } if(input.hasNextInt())//判斷類型是否正確 { k=input.nextInt();//類型正確輸入k } else//類型不正確報錯並結束程序 { System.out.println("輸入錯誤!"); System.exit(0); } if(n>0&&k>=0&&n>=k)//判斷n和k的值是否合法且n>=k是否成立 { System.out.println("結果為:"+calculateC(n,k));//成立,輸出結果 } else//n<k,無法進行運算,報錯並結束程序 { System.out.println("輸入錯誤!"); System.exit(0); } } public static int calculateC(int n,int k)//計算相應的組合數 { if(k==0||k==n)//C_n^0=1或C_n^n=1 { return 1; } else if(k==1)//C_n^1=n { return n; } else//利用公式//C_n^k=C_n-1^k-1+C_n-1^k { return calculateC(n-1,k-1)+calculateC(n-1,k); } } }
4.結果截圖
課後作業2
1. 程序設計思想
⑴ 提示用戶輸入盤子數量。
⑵ 調用方法解決漢諾塔問題。
將n個盤子從第一根柱子移到第三根柱子上的方法為:①先將n-1個盤子借助第三根柱子移到第二根柱子上。②再將第一根柱子上的最大的盤子移到第三根柱子上。③然後將第二根柱子上的n-1個盤子借助第一根柱子移到第三根柱子上。
將n-1個盤子從第二根柱子上移到第三根柱子上的方法為:①先將n-2個盤子借助第三根柱子移到第一根柱子上②再將第二根柱子上的最大的盤子移到第三根柱子上。③然後將第一根柱子上的n-2個盤子借助第二根柱子移到第三根柱子上。
而移動n-2個盤子的方法又類似於移動n個盤子的方法,以此類推。上述的第一、二、三根柱子可視為初始柱、過渡柱以及目標柱。移動n個盤子三步可視為:①將n-1個盤子由初始柱借助目標柱移到過渡柱。②將初始柱上的最大的盤子直接移到目標柱。③將n-1個盤子由過渡柱借助初始柱移到目標柱。借助遞歸的方法可解決漢諾塔的問題。
⑶ 在方法中,先判斷盤子數量是否為1,若為1,則直接將第一根柱子上的盤子移到第三根上;否則,先將n-1個盤子移動到過渡柱上,再將初始柱上的盤子移到目標柱上,再將n-1個盤子由過渡柱移到目標柱上。遞歸調用該方法,每次調用移動的盤子是上一次減一個。
⑷ 直到算出結果,將結果顯示在屏幕,程序結束。
2. 程序流程圖
3. 程序源代碼
import java.util.Scanner; public class Hanoi { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("請輸入要放的盤子數量:");//提示用戶輸入盤子數量 Scanner input=new Scanner(System.in); int amount=0; if(input.hasNextInt()) { amount=input.nextInt();//用戶輸入數量 } else { System.out.println("輸入錯誤!"); System.exit(0); } if(amount>=1)//判斷用戶輸入的盤子數量是否合法 { hanoi(amount,‘A‘,‘B‘,‘C‘);//調用函數解決漢諾塔問題 } else { System.out.println("輸入錯誤!");//用戶輸入有誤 } } public static void hanoi(int amount,char a,char b,char c)//解決漢諾塔問題 { if(amount==1)//如果盤子數量為1,則直接將其移動到目標柱上 { move(a,c);//移動盤子的函數 } else { hanoi(amount-1,a,c,b);//先將n-1個盤子移到過渡柱上 move(a,c);//將初始柱上的盤子移到目標柱上 hanoi(amount-1,b,a,c);//將n-1個盤子從過渡柱移到初始柱上 } } public static void move(char a,char c)//移動盤子 { System.out.println(a+"--->"+c);//顯示從初始柱移到目標柱的過程 } }
4.結果截圖
課時作業3
1. 程序設計思想
① 提示用戶輸入字符串。
② 將字符串類型數據轉成字符數組便於比較對稱位置上的字符。
③ 定義判斷是否是回文的方法,參數為每次要判斷的字符的位置。若字符的位置超過字符數組的的一半,說明字符串為回文;判斷一對對稱位置上的字符是否一致,若一致則判斷下一對對稱位置上的字符是否一致,如不一致則不是回文。
④ 在主函數中調用判斷是否一個字符串是否為回文的方法,因為在數組中一個元素下標為0,所以調用時參數應為0,並做相應輸出。
2. 程序流程圖
3. 程序源代碼
import java.util.Scanner; public class Palindrome { /** * @param args */ static char[] str;//定義全局變量字符數組用於放字符串 public static void main(String[] args) { // TODO Auto-generated method stub System.out.println("請輸入要判斷的字符串:");//提示用戶輸入字符串 Scanner input=new Scanner(System.in); String string=input.next();//用戶輸入字符串 str=string.toCharArray();//將字符串轉為字符數組便於比較對稱的字符是否相同 if(judge(0))//因為在字符數組中第一個字符的下標為0,所以從0開始判斷 { System.out.println(string+"是回文!");//顯示用戶輸入的字符串為回文 } else { System.out.println(string+"不是回文!");//顯示用戶輸入的字符串不是回文 } } public static boolean judge (int n)//判斷字符串是否是回文 { if(n>=str.length/2)//遞歸結束的條件:當比較的字符超過字符數組的一半時,說明此時仍沒有出現對稱位置上的字符不相等的情況,則此字符串為回文 { return true;//返回true } else if(str[n]==str[str.length-1-n])//比較字符數組的對稱位置上的字符是否一致 { return judge(n+1);//若對稱位置上的字符一致,則判斷後一對對稱位置上的字符 } else { return false;//遞歸結束的條件:出現對稱位置上的一對字符不一致的情況,則此字符串不是回文,返回false } } }
4. 結果截圖
5.實驗總結
在本題中用toCharArray函數將字符串轉為字符數組便於判斷,判斷時通過判斷每一對稱位置上的元素是否一致來判斷字符串是不是回文,判斷時應從第一個元素位置開始判斷,在此處應註意參數為0不是為1,因為在數組中第一個元素下標為0。一致則通過將參數加一來實現位置的移動,當參數位置超過數組長度一半時則為回文,判斷有不一致的元素時則不是回文。
遞歸運用實例