全排列 3 种方法整理(递归,多路递归,前缀)

全排列 3 种方法整理(递归,多路递归,前缀)

关于全排列的问题描述就不再赘述了,这里整理出 3 种求一个集合中所有元素的全排列的方法。

一、递归 n-1 层

在这里插入图片描述
处理 n-1 层(n == 1 时返回),对 n-1 层的所有元素进行 “补左”,“补右”,“补中间”三个操作,得到 n 层。

注意 “补中间” 操作可能涉及多个位置。
在这里插入图片描述
参考代码:

// 递归 
void getPermutation(string arr, int n){
	// 出口 当n == 1时,只有一个元素 
	if(n == 1){
		// 使用字符数组辅助 
		char ch[1];
		ch[0] = arr[0];
		string temp(ch, 1);
		pre.insert(temp);
		return;
	}
	// 处理好n-1层 
	getPermutation(arr, n-1);
	// 对n-1层的每一个元素都按三种不同的组合方式加上新字符arr[n-1] 
	for(set<string>::iterator it = pre.begin(); it != pre.end(); it++){
		string str = *it;
		permutationSet.insert(str+arr[n-1]);
		permutationSet.insert(arr[n-1]+str);
		for(int i = 1; i < str.length(); i++){
			permutationSet.insert(str.substr(0, i)+arr[n-1]+str.substr(i));
		}
	}
	// 注意更新pre 以及置零permutationSet 
	pre = permutationSet;
	permutationSet.clear();
}
二、多路递归

在这里插入图片描述
利用了回溯的思想,每层对括号中的每一个元素,取出来加入已经选择的集合,这样成为了下一层。

后面的层都遵循这样的逻辑,直到括号内没有元素。

但是需要保留父亲的状态才能得到其他的支路(因为父节点是共享的)

参考代码:

// 回溯 多路递归 
void getPermutation(string &arr, int k){
	if(k == arr.length()){
		permutationSet.insert(arr);
		return;
	}
	for(int i = k; i < arr.length(); i++){
		swap(arr[k], arr[i]);  // 交换 
		getPermutation(arr, k+1);  // 递归 
		swap(arr[k], arr[i]);  // 回溯 
	}
} 
三、前缀

在这里插入图片描述
中括号 [ ] 中的字符串为前缀,每次只要遍历集合查看有哪些字符没有在前缀 prefix 中,

分别加在前缀的后面继续进行递归。

参考代码:

// 前缀 可以求出第几个排列 
void getPermutation(string arr, int n, string prefix){
	if(prefix.length() == n){
		permutationSet.insert(prefix); 
		return;
	}
	for(int i = 0; i < n; i++){
		if(count(prefix, arr[i]) < count(arr, arr[i])){
			getPermutation(arr, n, prefix+arr[i]);
		}
	}
} 

【END】感谢观看

发布了44 篇原创文章 · 获赞 17 · 访问量 9111

猜你喜欢

转载自blog.csdn.net/qq_41765114/article/details/88406965