0
点赞
收藏
分享

微信扫一扫

【算法】递归实现排列、组合

逸省 2022-04-07 阅读 21

文章目录

1.排列

从char[ ] arr数组中进行排列出 n位数(长度)的字符串(n<=arr.length)。

a.不带注释:

public class test5 {

	public static void main(String[] args) {
		char[] arr = new char[] {'1','2','3','4','5','6','7','8','9'};
		n = 9;
		v(arr,0);
	}
	
	static int n;
	static StringBuilder builder = new StringBuilder();
	
	public static void v(char[] arr,int count) {
		if(count==n) {
			System.out.println(builder.toString());
			return;
		}
		for(int i=0;i<arr.length;i++) {
			if(builder.indexOf(""+arr[i])==-1){
				builder.insert(count, arr[i]);
				v(arr,count+1);
				builder.delete(count, builder.length());
			}
		}
	}
}

 

b.带注释:

public class Main {
	public static void main(String[] args) {
		// 开始时间
		long start = System.currentTimeMillis();
		
		// 调用方法
		char[] arr = new char[] {'1','2','3','4','5','6','7','8','9'}; // 使用char数组,可以对任意字符进行排列
		n = 9; // 排列9位数
		
		/**
		*	每一层的数字都有可能是1-9,当某一层的数字在已有的StringBuilder中没有时,即可选.
		*	builder = "138945";
		*	builder = "1389572";
		*	builder = "138957246";
		*	builder = "138957246";
		*	// 满足输出,退回上一层 "13895724",继续从for循环i=7开始往下走,末找到符合的数,结束当前层数,
		*	// 继续即回上层 "1389572" 继续从for循环i=5开始往下走,找到6。"13895726",进入下一层
		*	// 找到 "4"。"138957264",到达第n层,输出.
		*/ 
		v(arr,0);
		
		// 结束时间
		long end = System.currentTimeMillis();
		System.out.println("排列总数: "+k);
		System.out.println("时间: "+(end-start)+"ms");
		// 1484-1820ms
	}
	
	static int n;	// 需要排列的字符个数,如 排列:4位数(1234),5位数(34567)
	static StringBuilder builder = new StringBuilder();	// 存放排列好的字符串
	static int k = 0; // 统计排列的字符组数量 
	
	public static void v(char[] arr,int count) {
		// count: 从0开始递归,每一层生成一个数,进行n层递归生成n位排列数
		if(count==n) {
			// 输出该排列好的字符组
			System.out.println(builder.toString());
			k++;
			// 结束当前方法,返回上一层往下查找排列。
			return;
		}
		// 查找排列,从下标0开始,获取字符arr[i]
		for(int i=0;i<arr.length;i++) {
			// 若字符arr[i]不存在于arr数组前面已有的数,即满足
			if(builder.indexOf(""+arr[i])==-1){
				// 插入到位置count中(这里可以用builder.replace方法替换,同时省去delete方法)
				builder.insert(count, arr[i]);
				// 进行下一层,即count+1
				v(arr,count+1);
				// 删除上一次排列好第count之后的字符
				builder.delete(count, builder.length());
			}
		}
	}

}

 
 

2.组合

从char[ ] arr数组中组合出 n位数(长度)的字符串

a.不带注释:

public class test6 {

	public static void main(String[] args) {
		char[] arr = new char[] {'1','2','3','4','5','6','7'};
		v(arr,0,0);
	}
	
	static int n = 4;
	static StringBuilder builder  = new StringBuilder(); 
	
	public static void v(char[] arr,int count,int start) {
		if(count==n) {
			System.out.println(builder.toString());
			return;
		}
		for(int i=start;i<arr.length;i++) {
			builder.insert(count, arr[i]);
			v(arr,count+1,i+1);
			builder.delete(count, builder.length());
		}
	}

}

 

b.带注释:

public class test6 {

	public static void main(String[] args) {
		
		// 同样是char[]数组 
		char[] arr = new char[] {'1','2','3','4','5','6','7'};
		
		/**
		 * 例:从arr数组中组合出 4位数(n=4)		
		 * 第一个数(层)是	0-4		(start)-(length-n+count+1)
		 * 第二个数是		1-5		(start+1)-(length-n+count+1)
		 * 第三个数是		2-6		...
		 * 第四个数是		3-7		....
		 * 综上,每一层的可选的数的范围是{i,arr.length-n+count+1}
		 * i是上一层已组合进去的数+1,i初始为0 
		 */
		v(arr,0,0);
	}
	
	static int n = 4;  // 组合 4位数
	static StringBuilder builder  = new StringBuilder(); // 存放组合好的字符串
	
	// 参数count用于记录所在的层数
	// 参数start用于for循环初始位置,因为下一个数肯定是在上一个数之后产生,如:已有 12或 14,
	// 那么下一个数(第三个数)肯定是大于 2或 4
	public static void v(char[] arr,int count,int start) {
		// 到达第n层即已经组合好 4位数的字符串
		if(count==n) {
			// 输出
			System.out.println(builder.toString());
			// 结束当前方法
			return;
		}
		// start开始的位置在上一个数之后,start在调用该方法时赋值为0,即第一个数从char[0] = 1 开始
		for(int i=start;i<arr.length;i++) {
			// 插入
			builder.insert(count, arr[i]);
			// 下一层
			v(arr,count+1,i+1);
			// 删除
			builder.delete(count, builder.length());
		}
	}

}
举报

相关推荐

0 条评论