《Java数据结构跟算法》第二版 Robert lafore 编程作业 第六章

《Java数据结构和算法》第二版 Robert lafore 编程作业 第六章

《Java数据结构和算法》第二版 Robert lafore  编程作业 第六章

/*
 	6.1	假设买了一个价格便宜的掌上电脑,但是发现它内置的芯片不能做乘法,只能做
 		加法。摆脱这种窘境需要自己编写程序,写的是一个递归的方法mult(),它的参
 		数是x和y返回值是x乘它.当这个方法调用自身或者当它返回的时候,加法是否起
 		作用了?
 	6.2	在第8章"二叉树"中,我们将看到二叉树,在它的每一个节点中确实有两个子树。
 		如果使用字符在屏幕上画一棵二叉树,可以在顶层有一个节点,在下一层有两个,
 		然后是4、8、16个,依此类推。下面是一棵最底层有16个字符的树的样子:
 		--------X-------
		----X-------X---
		--X---X---X---X-
		-X-X-X-X-X-X-X-X
		XXXXXXXXXXXXXXXX
		(注意最下面的一行,应当向右移动半个字符宽,但是在字符模式中做不到。)
		可以使用递归的makeBranches()方法来画这个树,这个方法的参数为left和
		right,它们是水平范围的端点。当第一次进入这个程序的时候,left等于0,而
		且right是所有行中字符的数目(包括短线)减一。在这行范围的中间画一个X。
		然后这个方法调用自己两次:一次左一半的范围,一次右一半的范围。当这个范
		围太小的时候返回。你可能想要把所有的短线和X都放到一个数组中,并且一次性
		显示数组,或许可以使用display()方法。编写main()调用makeBranches()和
		display()来画这棵树。允许main()决定显示的每一行的宽度(32,64或者其他
		的任何值)。确保存放显示字符的数组不会比所需要的空间大。行数(图中为五)
		和每一行的宽度有什么关系?
	6.3	应用递归的算法来实现求一个数的乘方,如在这一章接近结尾处的"求一个数的乘
		方"部分所讲。写递归的power()方法以及一个main()来测试它。
	6.4	写一个能解决背包问题的程序,任意给定背包的容量以及一系列物品的重量,设
		把这些重量值存在一个数组中。提示:递归方法knapsack()的参数是目标重量和
		剩下物品开始位置的数组下标。
	6.5	应用一个递归的方法来显示由一群人组队的所有可能方案(由n个人每次挑k个)。
		编写递归的showTeams()方法和一个main()方法来提示用户输入人群的人数以及
		组队的人数,以此来作为showTeams()的参数,然后显示所有的组合。
 */
package chap06;

//=======================================================================
//编程作业 6.1
public class Multiplication {
	// multiplicand 被乘数
	// multiplier 乘数
	// multiply 乘
	public int multiply(int multiplicand, int multiplier) {
		if (multiplier == 1) {
			return multiplicand;
		} else {
			return multiplicand + multiply(multiplicand, multiplier - 1);
		}
	}

	public static void main(String[] args) {
		Multiplication mutiplication = new Multiplication();
		int result = mutiplication.multiply(6, 8);
		System.out.println(result);
	}
}
// =======================================================================
package chap06;

// =============================================================================
// 编程作业 6.2
public class BinaryTreeShow {
	private char[][] lines;

	// number 一行最大显示字符数
	public BinaryTreeShow(int number) {
		int rows = 1;
		int numberDivide = number;// 不要直接用number去除,后面还有用到number
		while ((numberDivide = numberDivide / 2) != 0) {// 行数 number和row的关系
			rows++;							// 2^(row-1) = number 2^(5-1)=16
		}									// 当number=16时,row=5
		lines = new char[rows][number];
		for (int i = 0; i < rows; i++) { // 初始化数组
			for (int j = 0; j < number; j++) {
				lines[i][j] = '-';
			}
		}
	}

	public void display() {
		for (int i = 0; i < lines.length; i++) { // 初始化数组
			for (int j = 0; j < lines[i].length; j++) {
				System.out.print(lines[i][j]);
			}
			System.out.println();
		}
	}

	public void makeBranches(int left, int right) {
		int number = right - left + 1;
		int row = 0;
		int muberDivide = number; // 不要直接用number去除,后面还有用到number
		while ((muberDivide = muberDivide * 2) <= lines[0].length) {
			row++;// 计算当前行号
		}
		if (number == 1) {// 基值条件
			lines[row][left] = 'X';
			return;
		} else {
			int mid = (left + right) / 2 + 1;
			lines[row][mid] = 'X';
			makeBranches(left, mid - 1);
			makeBranches(mid, right);
		}
	}

	public void makeTree() {
		makeBranches(0, lines[0].length - 1);
	}

	public static void main(String[] args) {
		BinaryTreeShow binaryTreeShow = new BinaryTreeShow(16);
		binaryTreeShow.makeTree();
		binaryTreeShow.display();
	}
}
// =============================================================================
package chap06;

//编程作业 6.3
//mathematics 数学,数学运算
//int的范围 [-2^32~2^31-1] -2147483648到2147483647
public class Mathematics {
	// 求x的y次方 x^y
	// 对于 y总是偶数时
	// 2^8 = (2*2)^(8/2)= 4^4
	// 4^4 = (4*4)^(4/2)=16^2
	// 16^2 = (16*16)^(2/2) = 256^1
	// 256^1 = 256
	// 对于y出现是奇数时
	// 3^18 = (3*3)^(18/2) = 9^9
	// 9^9 = 9*(9^8)= 9*((9*9)^(8/2)) = 9*(81^4)
	// 9*(81^4)=9*((81*81)^(4/2))=9*(6561^2)
	// 9*(6561^2)=9*((6561*6561)^(2/2))=9*43046721^1
	// 9*43046721^1 = 9*43046721
	public int power(int x, int y) {
		if (y == 1) {
			return x;
		} else {
			if (y % 2 == 0) {
				return power(x * x, y / 2);
			} else {
				return x * power(x * x, y / 2);
			}
		}
	}

	public static void main(String[] args) {
		Mathematics mathematics = new Mathematics();
		int result = mathematics.power(3, 18);
		System.out.println(result);
	}
}
package chap06;

// =============================================================================
// 编程作业 6.4
public class Knapsack {
	private int[] weights; // 可供选择的重量
	private boolean[] selects; // 记录是否被选择

	public Knapsack(int[] weights) {
		this.weights = weights;
		selects = new boolean[weights.length];
	}

	// 找所有可能的解
	// total总重量
	// index可供选择的重量
	public void knapsack(int total, int index) {
		if (total < 0 || total > 0 && index >= weights.length) {// 基值,没找到解
			return;
		}
		if (total == 0) { // 基值,找到解
			for (int i = 0; i < index; i++) {
				if (selects[i] == true) {
					System.out.print(weights[i] + " ");
				}
			}
			System.out.println();
			return;
		}
		selects[index] = true;
		knapsack(total - weights[index], index + 1);
		selects[index] = false;
		knapsack(total, index + 1);
	}

	public static void main(String[] args) {
		Knapsack knapsack = new Knapsack(new int[] { 11, 8, 7, 6, 5, 4, 3 });
		knapsack.knapsack(20, 0);
	}
}
// =============================================================================
package chap06;

//编程作业 6.5
//方法一
public class Group {
	private char[] persons; // 组中所有可供选择的成员
	private boolean[] selects; // 标记成员选中与否

	public Group(char[] persons) {
		this.persons = persons;
		selects = new boolean[persons.length];
	}

	public void showTeams(int teamNumber) {
		showTeams(persons.length, teamNumber);
	}

	// =============================================
	// 找所有可能的解
	// totalNuber 总共有多少人供选择
	// teamNuber 需要选择多少人
	// =============================================
	// 从个n人中取出k个人的所可能方案,表示为方法参数(n,k)
	// 求(n,k)的所有解
	// 当k=0时得一个解,n<k时无解
	// 否则(n,k)-->(n-1,k-1)+(n-1,k)
	// =============================================
	// 列如 :从3个人中选2个人,此时参数为(3,2)
	// (3,2)-->(2,1)+(2,2)-->(1,0)+(1,1)+(1,1)+(1,2)
	// (1,0)得到一个解,(1,2)无解
	// (1,0)+(1,1)+(1,1)+(1,2)-->(1,1)+(1,1)
	// (1,1)+(1,1)-->(0,0)+(0,1)+(0,0)+(0,1)
	// (0,0)得到一个解,(0,1)无解
	// 所以(3,2)一共有 3个解
	// 列如 :从3个人中选3个人,此时参数为(3,3)
	// (3,3)-->(2,2)+(2,3)-->(2,2)-->(1,1)+(1,2)-->(1,1)-->(0,0)+(0,1)-->(0,0)
	// 即(3,3)有一个解
	// =============================================
	private void showTeams(int totalNumber, int teamNumber) {
		if (teamNumber == 0) { // teamNumber=0时, 找到一个解
			for (int i = 0; i < selects.length; i++) {
				if (selects[i] == true) {
					System.out.print(persons[i] + " ");
				}
			}
			System.out.println();
			return;
		}
		if (totalNumber < teamNumber) { // totalNuber< teamNumber,无解
			return;
		}
		selects[persons.length - totalNumber] = true;
		showTeams(totalNumber - 1, teamNumber - 1);
		selects[persons.length - totalNumber] = false;
		showTeams(totalNumber - 1, teamNumber);
	}

	public static void main(String[] args) {
		Group group = new Group(new char[] { 'A', 'B', 'C', 'D', 'E' });
		group.showTeams(3);
	}
}
package chap06;

//编程作业 6.5
//方法二
public class Group1 {
	private char[] persons; // 组中所有可供选择的成员
	private boolean[] selects; // 标记成员选中与否

	public Group1(char[] persons) {
		this.persons = persons;
		selects = new boolean[persons.length];
	}

	public void showTeams(int teamNumber) {
		showTeams(teamNumber, 0);
	}

	// =============================================
	// 找所有可能的解
	// teamNumber需要选择的队员数
	// index从第几个队员开始选择
	// =============================================
	// 从n个人中取出k个人的所可能方案
	// 此处方法参数有些变化(n,k)应写成(k,i)(i=0,1,2,...)
	// 当k=0时得一个解,i>=n时无解
	// 否则(k,i)-->(k-1,i+1)+(k,i+1)
	// =============================================
	// 列如 :从3个人中选2个人,
	// 参数应写成(2,0)
	// (2,0)-->(1,1)+(2,1)-->(0,2)+(1,2)+(1,2)+(2,2)
	// (0,2)得一解
	// (1,2)+(1,2)+(2,2)-->(0,3)+(1,3)+(0,3)+(1,3)+(1,3)+(2,3)
	// (0,3)得一解,(1,3)无解,(2,3)无解,有两个(0,3)
	// 所以(2,0)有三个解
	// =============================================
	private void showTeams(int teamNumber, int index) {
		if (teamNumber == 0) { // 当teamNuber=0时 找到
			for (int i = 0; i < selects.length; i++) {
				if (selects[i] == true) {
					System.out.print(persons[i] + " ");
				}
			}
			System.out.println();
			return;
		}
		if (index >= persons.length) {// index超过可供选择的人的数,未找到
			return;
		}
		selects[index] = true;
		showTeams(teamNumber - 1, index + 1);
		selects[index] = false;
		showTeams(teamNumber, index + 1);
	}

	public static void main(String[] args) {
		Group1 group = new Group1(new char[] { 'A', 'B', 'C', 'D', 'E' });
		group.showTeams(3);
	}
}