含重复元素序列的全排列
2013-12-07 01:01
246 查看
对于n个不同元素集合R的全排列问题,可以用一个简单递归的公式表达:
当n = 1时, P(R) = r, 否则
P(R) = ri + P(R - {ri}) (i = 1, 2, ..., n)
P(R) : 不含重复元素的R集合的全排列
+: 表示连接
根据上面的公式写出递归计算出无重复元素序列的全排列:
Perm(Type list[], int k, int m)
if k=m
then print( list )
else
for i=k to m do
Swap( list[k],list[i] );
Perm(list,k+1,m);
Swap(list[k],list[i]);
1. 对于含有重复元素的序列,我们不能再像上面那样简单的交换与来求解。因为,当ri 到rk 的序列中,如果存在元素 rj = rk 且 j != k 。这时,rj 必然是已经和 ri 交换过位置,并且计算了 rj + P(R{i...n} - {rj}) 。如果再将 rk 与 ri 与交换,则会得到 rk + P(R{i...n} - {rk}) 这个全排列,而rj = rk,所以,我们第二次计算多余了。
2. 再考虑当从ri 到rk 的序列中,如果不存在有元素 rj = rk , 那么,这时的情况是和普通计算时过程一样,交换ri 与rk 然后求解 就可以了,因为即使在后面存在与其他重复元素,我们也会在计算中按第1步剪掉重复计算。
所以,在求解时我们只要保证交换某一元素时,其未有在i...j之间出现过。否则交换后必会重复求解。
下面是求有重复元素的全排列的源码(我参考网上的写的):
当n = 1时, P(R) = r, 否则
P(R) = ri + P(R - {ri}) (i = 1, 2, ..., n)
P(R) : 不含重复元素的R集合的全排列
+: 表示连接
根据上面的公式写出递归计算出无重复元素序列的全排列:
Perm(Type list[], int k, int m)
if k=m
then print( list )
else
for i=k to m do
Swap( list[k],list[i] );
Perm(list,k+1,m);
Swap(list[k],list[i]);
1. 对于含有重复元素的序列,我们不能再像上面那样简单的交换与来求解。因为,当ri 到rk 的序列中,如果存在元素 rj = rk 且 j != k 。这时,rj 必然是已经和 ri 交换过位置,并且计算了 rj + P(R{i...n} - {rj}) 。如果再将 rk 与 ri 与交换,则会得到 rk + P(R{i...n} - {rk}) 这个全排列,而rj = rk,所以,我们第二次计算多余了。
2. 再考虑当从ri 到rk 的序列中,如果不存在有元素 rj = rk , 那么,这时的情况是和普通计算时过程一样,交换ri 与rk 然后求解 就可以了,因为即使在后面存在与其他重复元素,我们也会在计算中按第1步剪掉重复计算。
所以,在求解时我们只要保证交换某一元素时,其未有在i...j之间出现过。否则交换后必会重复求解。
下面是求有重复元素的全排列的源码(我参考网上的写的):
int ok(char *origin, int x, int y) { int i; if(y > x) for(i = x; i < y; i++) if(origin[i] == origin[y]) return 0; return 1; } void permutation(char *origin, int curLen, int maxLen) { int i; if(curLen >= maxLen - 1) { puts(origin); fprintf(fpout, "%s\n", origin); } else { for(i = curLen; i < maxLen; i++) if(ok(origin, curLen, i)) { swap(&origin[i], &origin[curLen]); permutation(origin, curLen + 1, maxLen); swap(&origin[i], &origin[curLen]); } } }
相关文章推荐
- 求输入字符串的全排列 (无重复元素)
- leetcode-46. Permutations(非重复元素全排列)
- leetcode-47. Permutations II(重复元素全排列)
- UVA 10635 Prince and Princess [序列无重复元素时 LCS转换成LIS问题求解 O(nlogn) ]
- LintCode 15-全排列 16-带重复元素的全排列
- 计数与概率基础(容斥、有重复元素的全部排列、可重复选择的全排列、杨辉、二项式定理、欧拉函数)
- 输出一组元素的全排列(可包含重复元素)
- 包含重复元素的全排列
- 非递归实现不重复序列的全排列(一)
- 如何得到有重复元素的不重复全排列
- 非递归实现不重复序列的全排列(一)
- 集合的全排列(可包含重复元素)
- 含重复元素的全排列
- Search for a range, 在一个可能有重复元素的有序序列里找到指定元素的起始和结束位置
- 递归实现全排列(可包含重复元素)
- 非递归实现不重复序列的全排列(二)
- 单词的全排列同时去重复的元素
- 对有重复元素的字符串进行全排列
- LintCode 带重复元素的子序列
- 非递归实现不重复序列的全排列(二)