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

递归是一个方法调用方法自己本身去解决问题,这是个比较神奇也实用的功能。本篇是为了解决《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));
	}
}
结果如下:

1
10
100
1000
10000
100000

题二:背包问题

背包问题是计算机科学里的经典问题。在最简单的形式中,包括试图将不同重量的数据项放到背包中,以使背包最后达到指定的总重量。不需要把所有的选项都放入背包中。假如一个背包最多能放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

你可能感兴趣的:(组合,递归,背包问题,乘方,java实现组合)