递归经典案例:在n个球中任意取出m个,有多少中取法 、 求 n个元素的全排列、 求两个串的最大公共子序列的长度

package digui;
/**
 * @author : HuXuehao
 * @date : 2021年3月2日下午5:26:14
 * @version : 
*/
public class classical_case {
	/*
	 * 一、在n个球中任意取出m个,有多少中取法
	 * 例如:从 abcd 4个球中取出 2 个球
	 *     所有情况举例:ab ac ad bc bd cd
	 *     思路:从上述中我们可以发现,取出的球可以分为两个阵列,一个是含有a(也可以是其他)的,
	 *     		一个是不含有a的
	 *     总结:① ab ac ad 可以理解成默认取出的球中含有a,也就是从n-1(因为a默认已经取出)个
	 *     		球中取出m-1(因为默认已经取出a了)个球;② bc bd cd 是不含有a的球,可以理解成
	 *     		取出的球中不能含有a,也就是从n-1(把a排除在外,才能保证取出的球不含有a)中取出
	 *     		m个球
	 */
	public static int getTargetNum(int n, int m) {
		if(n < m) return 0; //当n < m时,无法取球
		if(n == m ) return 1; //当n == m时,只有一种可能性
		if(m == 0) return 1; //当取出0个球时,认为只有一种可能
		
		return getTargetNum(n-1, m-1)/*①*/ + getTargetNum(n-1, m)/*②*/;
	}
	
	/* 二、求 n个元素的全排列
	 * 方案1:(思路没有问题,没有通过代码实现,我猜测它的时间复杂度会很大)
	 * 思路:求n个元素的全排列时,先求出n-1个元素的全排列x,将第一个元素插入每个全排列x的不同位置
	 *      求n-1个元素的全排列x时,先求n-2个元素的全排列y,将第n-1个元素插入每个全排列y的不同位置
	 *      ......
	 * 例如: dabc
	 * 		求 abc 的全排列
	 * 		求bc 的全排列
	 * 	        (c的全排列)求c的全排列:
	 * 			c
	 * 	        (bc的全排列)将b 依次插入到 c 的全排列的空隙中得到bc的全排列:
	 * 			bc cb
	 * 	        (abc)将a 依次插入到每一个bc的全排列的空隙中得到abc的全排列:
	 * 			abc acb bac bca cab aba
	 * 	        (dabc)将 d 依次插入到 bc 的全排列的空隙中得到dabc的全排列:
	 * 			dabc adbc abdc abcd
	 * 			dacb adcb acdb acbd
	 * 			dbac bdac badc bacd
	 * 			dbca bdca bcda bcad
	 * 			dcab cdab cadb cabd
	 * 			daba adba abda abad
	 * 
	 * 方案2:(重点理解)***
	 * 例如:abc 
	 * abc acb bac bca cab cba
	 * 我们不难发现,将数组中的每一个元素与第一个元素进行交换,然后进行全排列 	   
	 */
	public static void allSort(char []data,int key) {
		if(key == data.length) {
			for(int i = 0;i < data.length; i++) {
				System.out.print(data[i] + "");
			}
			System.out.println();
		}
		for(int i = key; i < data.length; i++) {
//			试探
			{char t = data[key];data[key] = data[i];data[i] = t;}
			allSort(data, key+1);
//			回溯
			{char t = data[key];data[key] = data[i];data[i] = t;}
		}
	}
	
	/*
	 * 三、求两个串的最大公共子序列的长度(只是限于可解上面,软法的优化是很大的问题)
	 * 
	 */
	public static int maxPubSubList(String str1,String str2) {
		//出口
		if(str1.length() == 0 || str2.length() == 0) return 0;
		
		//如果第一个字符相等,那么就以下一个字符为开头的子串求最大公共子序列长度x,x+1就是两个串的最大公共子序列的长度
		if(str1.charAt(0) == str2.charAt(0)) {
			return maxPubSubList(str1.substring(1), str2.substring(1)) + 1;
		}else {
			//如果第一个不同,那么就尝试分别将其中一个的开头字符去掉,再分别求两个串最大公共子序列长度,最大公共子序列取长度长的
			return Math.max(maxPubSubList(str1, str2.substring(1)), maxPubSubList(str1.substring(1), str2));
		}
	}

	public static void main(String[] args) {
		/*System.out.println("------------------");
		int n = 5;
		int m =3;
		System.out.println(getTargetNum(n, m));
		
		System.out.println("------------------");
		char []c = "abcd".toCharArray();
		allSort(c, 0);*/
		
//		System.out.println("------------------");
//		System.out.println(maxPubSubList("abc", "eafbg"));
		System.out.println(0);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值