分治法实现全排列
来源:互联网 发布:c语言字符数组长度 编辑:程序博客网 时间:2024/04/28 16:39
转自 http://www.wutianqi.com/?p=1166
我们将使用分治法实现一个全排列算法。先来看一下算法实现后的效果:
permutation
["a", "b", "c"],
["a", "c", "b"],
["b", "a", "c"],
["b", "c", "a"],
["c", "b", "a"],
["c", "a", "b"]。
算法描述
分治法求解问题分为三个步骤:
- 分解:将问题分为若干个子问题。
- 解决:递归地求解每个子问题。
- 合并:将每个子问题的解合并成为整个问题的解。
现在我们需要求具有n个元素的数组A的全排列。例如:大小为3的数组A=[a,b,c] (为方便起见,我把引号全都省略了,其实应该是A=['a','b','c']。下同),它的全排列为:
[[a,b,c],
[a,c,b],
[b,a,c],
[b,c,a],
[c,a,b],
[c,b,a]]
这是一个大小为 n!*n 的二维数组。
使用分治算法求解全排列的过程如下
- 分解:将数组分为子数组 A[1..k-1] 和一个元素 A[k]。 (1≤k≤n)
- 解决:递归地求解每个子数组 A[1..k-1] 的全排列,直至子数组A[1..k-1]为空时结束递归。
- 合并:将上一步的结果—A[1..k-1]的全排列(一个二维数组)与元素A[k]合并,得出A[1..k]的全排列。例如:
[[]] 与 a 合并得到 [[a]]
[[a]] 与 b 合并得到 [[a,b], [b,a]]
[[a,b],[b,a]] 与 c 合并得到 [[a,b,c],[a,c,b],[c,a,b],[b,c,a],[c,a,b],[c,b,a]]
看下面的图示会更直观一些
1. 分解过程
[a,b,c]
/ \
[a,b] c
/ \
[a] b
/ \
[] a
2. 合并过程
[] a
\ /
[[a]] b
\ /
[[a,b],[b,a]] c
\ /
[[a,b,c],
[a,c,b],
[c,a,b],
[b,a,c],
[b,c,a],
[c,b,a]]
#include <cstring>#include <iostream>using namespace std;#define N 4char str[10];void Perm(char *str, int k, int m);void Swap(char &a, char &b);int main(){ int n; while(scanf("%d", &n) != EOF) { for(int i=0; i<=n; ++i) { str[i] = i+'0'; } Perm(str, 1, n); } return 0;} void Perm(char *str, int k, int m){ int i; if(k == m) { for(i=1; i<=m; ++i) cout<<str[i]<<" "<<flush; cout<<endl; return; } for(i=k; i<=m; ++i) { Swap(str[k], str[i]); Perm(str, k+1, m); Swap(str[k], str[i]); } } void Swap(char &a, char &b){ char tmp = a; a = b; b = tmp;}
上也是BUCT OJ 1140 分治法求解全排列问题的解答报告
但是对于字符串中存在重复的,比较1123,网上给出了这个源码:
http://fayaa.com/code/view/13115/
#include <iostream>#include <cstring> using namespace std; #define N 4 void Swap(char *pa, char *pb);void FullPermutation(char *str, int k, int n);int IsAppeared(char *str, char t, int begin, int end); char str[N+1] = "ADCD"; int main(){ FullPermutation(str, 0, N); return 0;} void Swap(char *pa, char *pb){ if(pa != pb) { char tmp = *pa; *pa = *pb; *pb = tmp; }} //判断字符t在字符串的下标begin到end处是否出现过int IsAppeared(char *str, char t, int begin, int end){ for(int j=begin; j<=end; ++j) { if(t == str[j]) return 1; } return 0;} /*对字符串进行全排列,注意该函数处理了字符重复的情况,字符重复的情况有两种: 1. str[i]本身和后面的str[k]相同 2. str[k]在k+1到i-1的下标之间已经出现过(用IsAppeared()函数去判断)*/void FullPermutation(char *str, int k, int n){ if(k == n) { cout<<str<<endl; return; } for(int i=k; i<n; ++i) { if(i!=k && (str[i]==str[k]) || IsAppeared(str,str[i],k+1,i-1)) ////用以处理元素重复的情况 continue; Swap(str+k, str+i); FullPermutation(str, k+1, n); Swap(str+k, str+i); }}
- 分治法实现全排列
- 分治法实现全排列
- 分治法实现全排列
- 分治法实现全排列
- 全排列的递归实现--分治策略
- 全排列算法实现 分治策略
- 分治与递归法:全排列问题
- 全排列之分治组合
- 采用分治法对数组元素进行全排列
- 问题 A 分治法求解全排列问题
- 递归实现全排列,字典序法实现全排列
- 递归法实现全排列
- 回溯法实现全排列
- 递归分治解决全排列问题
- 分治策略之全排列问题
- 分治案例_leetcode_46. Permutations-全排列
- 分治法输出排列
- 分治法求全排列
- 一些常用的几何相关在线计算工具
- Touch
- 一个计算机爱好者的不完整回忆(五十四)最高的荣誉
- 深入理解C++虚函数
- 机器学习--决策树(ID3)算法
- 分治法实现全排列
- Python 看书笔记(1)
- 01串
- R矩阵的索引
- 决策树的剪枝理论
- 一些计算机相关的在线工具
- SpringMvc 上传文件优化
- vim常用命令
- 15、 老项目在Xcode6调试运行时报错的问题(App installation failed).