您的位置:首页 > 其它

不重复排列的生成

2016-09-26 15:30 239 查看
全排列的话比较好打。

可,当一个集合中有许多重复的元素,如{2,2,2,2,2} 如何生成不重复的排列?

易知答案只有一个。

生成不重复排列,这很实用。

思想:把重复的数字不在看做多个元素,而是看做一个元素的多个个数。

然后递归生成时,添加在答案里的是次数的减少。

正确性:如果按照以上思路,那么可以知道,每个因为我们把重复的元素当做一个元素的多个来处理,那么当一个有重复的元素递归回来时,那么这个整个重复的元素就已经完成了它的赋值给ans,例如:执行2 1 1 的时候 会再递归回2 1 0的位置,但此时就不会在添加一遍 1, 而如果是全排列的话, 2 个 1 是不同的元素,后一个1 可能和 前一个交换位置,还是2 1 1。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAXN = 100 + 1;
int n, m;
int num[MAXN], ans[MAXN];
int vis[MAXN];

void init()
{
memset(num,0,sizeof(num));
memset(ans,0,sizeof(ans));
memset(vis,0,sizeof(vis));
m = 0;
}

inline void print()
{
for(int i = 1; i <= n; i ++)
printf("%d ", ans[i]);
printf("\n");
}

void dfs(int x)
{
if(x > n)
{
print();
return;
}
else{
for(int i = 1; i <= m; i ++)
{
if(vis[i] > 0)
{
vis[i] --;
ans[x] = num[i];
printf("ans[%d] = num[%d];\n", x, i);
dfs(x+1);
vis[i] ++;
}
}
}
}

int main()
{
while(cin >> n)
{
init();
for(int i = 1; i <= n; i ++)
{
int t;
scanf("%d",&t);
vis[i] ++;
bool re = false;
for(int j = 1; j <= m; j ++)
if(t == num[j])
{
vis[j] ++;
re = true;
break;
}
if(!re)
{
num[++m] = t;
}
}
dfs(1);
return 0;
}
return 0;
}

/*
3
1 1 2

1 1 2
1 2 1
2 1 1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  递归