c++非重复组合排列(含重复数字时,生成不重复组合排列)。
Sample Input
4
1 2 2 3
Sample Output
1223
1232
1322
2123
2132
2213
2231
2312
2321
3122
3212
3221
分析数据:这里和不含重复数据生成全组合排列代码是不同的,如果使用原代码会出现重复的数据,主要原因是在递归的时候,会把那些重复的数字当作不同的数字利用,而平等对待,直接进行递归。我们要做的就是把相同的数区分出来,我们这里可以引入一个数组mat,专门记录不同的数据,used数组记录每个数字出现的次数。
在递归的时候,因为数组mat的存储是不重复的,进而可以避免出现重复的组合。
又因为used记录的次数,程序可以知道在一个组合中每个数字用的次数,而可以在一个组合中,出现应该出现的重复
[cpp] view plaincopy
#include <iostream>
using namespace std;
const int len = 10;
int n;
int num;
int mat[len];
int result[len];
int used[len];
void push(int varNum);
void solve(int level);
int main()
{
cin>>n;
num=0;
for (int i=0;i<n;i++)
{
int var;
cin>>var;
push(var);
}
solve(0);
system(“pause”);
return 0;
}
/*———————-
操作的目的:生成一个数据全不重复的数组,并记录每个数出现的次数
初始条件:
n:记录选取数据的总长度
操作结果:
num:记录不重复数的个数(mat数组中数据的长度)
mat数组:存储不重复的数据
used数组:统计对应mat数组位置数据的出现次数
函数参数:
varNum:存储刚刚输入的数据,用来检测是不是重复的数据
————————*/
void push(int varNum)
{
for (int i=0;i<num;i++)
{
if (mat[i]==varNum)
{
used[i]++;
return;
}
}
mat[num]=varNum;
used[num]++;
num++;
}
/*———————-
操作的目的:普通选择性组合排列
初始条件:
n:记录选取数据的总长度
mat数组:存储选取数据
used数组:记录对应数据出现的次数
result数组:存储已得到的结果
操作结果:
输出result数组,所有的非重复组合排列
函数参数:
level:既代表递归的层次,也代表result数组已经处理到第几位了
一句话就是:把没用完的数放到result数组的第level位上
————————*/
void solve(int level)
{
if (level == n)
{
for (int i=0;i<n;i++)
{
cout<<result[i];
}
cout<<endl;
}
else
{
for (int i=0;i<n;i++) //这里的for循环是从0开始的,与例子的输出是对应的
{
if (used[i])//条件成立,还有没用的
{
result[level]=mat[i];
used[i]–;//标记已经用过一次
solve(level+1);
used[i]++;
}
}
}
}