递归三兄弟——数的乘方、背包问题、组合的Java实现

来源:互联网 发布:郑州it外包公司 编辑:程序博客网 时间:2024/05/01 01:33

递归是一个方法调用方法自己本身去解决问题,这是个比较神奇也实用的功能。本篇是为了解决《Java数据结构和算法》一书第六章递归中,最后留下的“三个有趣的问题”。

题一:求一个数的乘方

便携计算器中能够求一个数的乘方,通常是X^Y,表示求X的Y次方。但是如果没有这个键又改如何求捏?

解析:这是三个题目中最简单的,用递归求一个的乘方。代码如下:

package test.recursion;public class PowerQ {public int power(int x,int y) throws Exception{int result = 0;if(y < 0)throw new Exception("y不能小于0");else if(y == 0){//当y=0时,结果为1;result = 1;}else if(y/2 == 1)//当y/2时,就计算X*X;result = x*x;else //其他就递归result = power(x,y/2)*power(x,y/2);if(y%2 == 1)//当y除以2余数为1时,多乘一个X;result = result*x; return result;}public static void main(String[] args) throws Exception {PowerQ pq = new PowerQ();System.out.println(pq.power(10, 0));System.out.println(pq.power(10, 1));System.out.println(pq.power(10, 2));System.out.println(pq.power(10, 3));System.out.println(pq.power(10, 4));System.out.println(pq.power(10, 5));}}
结果如下:

110100100010000100000

题二:背包问题

背包问题是计算机科学里的经典问题。在最简单的形式中,包括试图将不同重量的数据项放到背包中,以使背包最后达到指定的总重量。不需要把所有的选项都放入背包中。假如一个背包最多能放20斤东西,现在有五个数据项可以用,分别是11斤、8斤、7斤、6斤、5斤。如何能正好达到20斤捏?

解析:需要正好达到20斤,没有数据项数目的要求。只能一个个的去遍历。代码如下:

package test.recursion;import java.util.ArrayList;public class BackpackQ {public int[] numbs;public ArrayList<Integer> adaptNumbs;public BackpackQ(int[] numbs){this.numbs = numbs;adaptNumbs = new ArrayList<Integer>();}public boolean adapt(int start,int max){boolean flag = false;for (int i = start; i < numbs.length; i++) {int temp = max - numbs[i];if(temp == 0) flag = true;else if(temp < 0) flag = false;else flag = adapt(i+1,temp);if(flag){adaptNumbs.add(numbs[i]);return true;}}return flag;}public static void main(String[] args) {int[] numbs = {11,8,7,6,5};BackpackQ bq = new BackpackQ(numbs);boolean adapt = bq.adapt(0, 20);System.out.println(bq.adaptNumbs.toString()+ adapt);}}
结果如下:

[5, 7, 8]

题三:选择一支队

在数学中,组合是对事物的一种选择,而不是考虑它们的顺序。例如:有5个登山队员,分别为ABCDE。要从五人中选三个人组成先头部队,需要列出所有可能的组合。

解析:大学中学过组合的知识,知道假如用(n,k)表示n个中选K个,那就有表达式:

(n,k)=(n-1,k-1)+(n-1,k)

那么5选3就可以变为 (5,3)=(4,2)+(4,3)然后继续递归每个子项,直到n个中选1个和n个中选n个为止。代码如下:

package test.recursion;import java.util.HashSet;import java.util.Set;public class TeamQ {public String[] items; //原始数据项public Set<String> rs; //set 可以防止出现重复项public TeamQ(String[] items,int k){this.items = items;String temp="";rs = new HashSet<String>();seek(items.length,k,temp); //开始调用递归方法}public void seek(int n,int k,String temp){if(k>1)// 当k>1时,(n-1,k-1)seek(n-1,k-1,temp+items[items.length-n]); if(n>k)// 当 n>k时,(n-1,k)seek(n-1,k,temp);if(k == 1){ //当k==1,即n中选1个,遍历剩下的数据项,每个结果添加到结果set中for (int i = items.length- n ; i < items.length; i++) {String tempIn = temp +items[i];rs.add(tempIn);}}if(k == n && k != 1){//当k==n且k!=1,即n中选n个,则将所有数据项一次性遍历,结果添加到结果set中String tempIn = temp;for (int i = items.length- n ; i < items.length; i++) {tempIn = tempIn +items[i];}rs.add(tempIn);}}public static void main(String[] args) {String[] sa = {"A","B","C","D","E"};TeamQ tq = new TeamQ(sa, 3);StringBuffer sb = new StringBuffer("数据项:");boolean isFirst = true;for (String str : sa) {if(!isFirst){sb.append(",");}sb.append(str);isFirst = false;}sb.append("\n中"+sa.length+"选"+3+"\n结果为:");isFirst = true;for (String str : tq.rs) {if(!isFirst){sb.append(",");}sb.append(str);isFirst = false;}System.out.println(sb.toString());}}
结果如下:

数据项:A,B,C,D,E中5选3结果为:BCD,ABD,ABC,ACE,ACD,BDE,BCE,ABE,ADE,CDE