遞迴的簡單應用
題目一
一個人趕著鴨子去每個村莊賣,每經過一個村子賣去所趕鴨子的一半又一隻。這樣他經過了七個村子後還剩兩隻鴨子,問他出發時共趕多少隻鴨子?經過每個村子賣出多少隻鴨子?
解題思路:因為是每經過一個村莊會賣掉一本又一隻,經過第七個村莊後還剩兩隻,按照要求,如果還經過一個村莊也就是第八個村莊後,鴨子數量就會為0,本題目解題使用一個count臨時變數來統計所經過的村莊的數目。使用遞迴的解法,當鴨子數目不為0或者1時就可以再去下一個村莊,而當前的鴨子數量就為(number/2-1)number表示鴨子數目。當前鴨子數量為為0時就可以返回經歷的村莊數目count
實現
/** * * @Title: Dunk.java * @Package one * @Description: 遞迴求得買鴨子問題 * @author: Jl * @date: 2018年11月17日 下午5:37:51 * @version V1.0 */ public class Dunk { static int count;//用來統計經過的村莊數量 /** * * @Title: sale * @Description: TODO(這裡用一句話描述這個方法的作用) * @author: Jl * @param: @param number 當前的鴨子數量 * @param: @return 當鴨子已經賣完就返回經過的村莊數量 * @return: int * @throws */ public static int sale(int number) { if(number==0) return count; if(number==1) return 1; count++; System.out.println("第"+count+"個"+"賣出"+(number/2+1)+"個"); return sale(number/2-1); //當前的鴨子數量只要不是0或者1就可以遞迴 } /** * * @Title: main * @Description: 因為經過七個村莊後還剩三隻鴨子,所以在經過第八個村莊後就會買光所有的鴨子 * @author: Jl * @param: @param args * @return: void * @throws */ public static void main(String[] args) { for(int j=0;j<1024;j += 2) {//從1到1024測試, count=0; if(sale(j)==8) {//只要滿足到第八個村莊後鴨子數量為0,該數量就是初始的數量。 System.out.println("總共的鴨子數目為:"+j); break; } } } }
題目二
角谷定理。輸入一個自然數,若為偶數,則把它除以2,若為奇數,則把它乘以3加1。經過如此有限次運算後,總可以得到自然數值1。求經過多少次可得到自然數1。
解題思路:此問題用遞迴會很好解決,只要判斷當前的值的奇偶性就可以按照要求進行下一次值得遞迴的代入
實現
package two; /** * * @Title: GuJiao.java * @Package two * @Description: 谷角定理 * @author: Jl * @date: 2018年11月17日 下午5:54:24 * @version V1.0 */ public class GuJiao { static int count = 0; //計算步數 /** * * @Title: getCount * @Description: 遞迴解決谷角定理 * @author:Jl * @param: @param number 當前所判斷的數 * @return:當值為1所經歷的步數 * @throws */ static public int getCount(int number) { count++; System.out.print(number+" "); if(number==1)//當前數為1,返回 return count; if(number%2==0) {//偶數就除以2 return getCount(number/2); } else {//奇數乘以3加1 return getCount(number*3+1); } } public static void main(String[] args) { for(int i=1;i<11;i++) { count = 0; System.out.println(" 進行:"+getCount(i)+"步"); } } }
題目三
電話號碼對應的字元組合:在電話或者手機上,一個數字如2對應著字母ABC,7對應著PQRS。那麼數字串27所對應的字元的可能組合就有3*4=12種(如AP,BR等)。現在輸入一個3到11位長的電話號碼,請打印出這個電話號碼所對應的字元的所有可能組合和組合數。
解題思路:本題目主要包括兩個方面,一個是獲取一個數字對應的字母的個數,另一方面是可以通過遞迴遍歷字串的每個字元,用當前字元所對應的字母個數乘以後面的字元所對應的個數,直到進行到最後一個字元
package three; /** * * @Title: NumberCombin.java * @Package three * @Description: 解決數字組合問題 * @author: Jl * @date: 2018年11月17日 下午5:44:59 * @version V1.0 */ public class NumberCombin { /** * * @Title: numberCount * @Description: 該方法用於求得每一個數字表示的可能的情況個數 * @author:Jl * @param: @param number 當前數字 * @param: @return * @return: int 當前數字表示的字母個數 * @throws 電話號格式異常 */ static public int numberCount(char number) { if(number=='1') return 0; if(number=='2'||number=='3'||number=='4'||number=='5'||number=='6'||number=='8') return 3; if(number=='7'||number=='9') return 4; else throw new RuntimeException("電話號碼格式不正確");//電話號格式錯誤 } /** * @Title: getCount * @Description: 用於使用者求組合個數的共有方法 * @author: Jl * @param: @param phoneNumber 電話號字串 * @return: int * @throws 電話號長度異常 */ static public int getCount(String phoneNumber) { if(phoneNumber.length()<3||phoneNumber.length()>11)//判斷長度是否符合要求 throw new RuntimeException("電話號碼長度不正確"); return getCount(phoneNumber,0); } /** * @Title: getCount * @Description: 過載的方法,該方法只要用於遞迴表示 * @author: jl * @param: @param phoneNumber 電話號字串 * @param: @param index 當前的字串進行計算的下標索引 * @return: 在index之前的組合可能數 * @throws */ static private int getCount(String phoneNumber,int index) { if(index==phoneNumber.length()) {//超出字串長度 return 1; }else { int curr = numberCount(phoneNumber.charAt(index)); return curr*getCount(phoneNumber,index+1);//從當前的*下一個的結果 } } public static void main(String[] args) { System.out.println(getCount("222222222223")); } }
題目四
日本著名數學遊戲專家中村義作教授提出這樣一個問題:父親將2520個桔子分給六個兒子。分完 後父親說:“老大將分給你的桔子的1/8給老二;老二拿到後連同原先的桔子分1/7給老三;老三拿到後連同原先的桔子分1/6給老四;老四拿到後連同原先的桔子分1/5給老五;老五拿到後連同原先的桔子分1/4給老六;老六拿到後連同原先的桔子分1/3給老大”。結果大家手中的桔子正好一樣多。問六兄弟原來手中各有多少桔子?
解題思路:本題目使用了倒推的思路,因為他們最後分到的橘子數目是一樣多的,所以,可以得到,每個人分到的橘子數為420個,而老六是把自己的1/3分給了老大,所以從這裡可以看出來老六得到老五橘子後的的橘子總數為420*3/2=630,分給老大的是210,因為老大最後的橘子數目為420,所以,在分給後,老六還沒有分給他橘子之前,還有210個,而老大把自己的1/8分給老二,所以在老大分給老二前的橘子數目為240,依次類推。沒有采用遞迴的實現思路
實現
package four;
/**
*
* @Title: Orange.java
* @Package four
* @Description: 解決“父親將2520個桔子分給六個兒子”的問題
* @author: Jl
* @date: 2018年11月17日 下午5:29:59
* @version V1.0
*/
public class Orange {
/**
* @Title: distri
* @Description: 該方法用來求解每人初始的橘子數量,主要是採用了倒推的方法。
* @author: Jl
* @param:
* @return: void
* @throws
*/
public static void distri() {
// 每個人最終的橘子數量一致,所以每個人最終都是420個橘子
int[] apple = new int[] { 420, 420, 420, 420, 420, 420 };// 最終的蘋果數量
for (int i = 1; i < 6; i++)// 求每個人得到橘子後的橘子數量
apple[i] = apple[i] * (8 - i) / (7 - i);
// 可以算出老六分給老大的橘子數量為210,所以,老大在分給老二後的橘子數量為210
apple[0] = 210 * 8 / 7; // 老大分給老二前的橘子數量
for (int i = 5; i > 0; i--)// 求得到橘子之前每個人的橘子數量,apple[i-1]/(9-i)表示從上一家得到的橘子
apple[i] = apple[i] - apple[i - 1] / (9 - i);
for (int i = 0; i < 6; i++) {
System.out.println("老" + (i + 1) + "的橘子數量為: " + apple[i]);
}
}
public static void main(String[] args) {
distri();
}
}