先给个基本方法,适用于序列中无重复元素的情况。
思想:一个一个生成,每次生成时,看该元素在前面有没有存在过
例如,生产第k个元素时,在1~n-1中找,前k-1个元素中没出现过的最小元素,给到a[k]。
//生成1~n的全排列
#include<stdio.h>
void printf_permutation(int n,int A[],int cur) //每次处理a[]的一个元素(位子)
{
int i,j;
if(cur == n)
{
for(i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
}
else
for(i=1;i<=n;i++) //先从小到大,取一个i
{
int ok =1;
for(j=0;j<cur;j++) //看前面的a[0] 到 a[cur] 中,i有没有出现过
if(A[j] == i) ok=0;
if(ok) //如果没有出现过,则
{
A[cur] = i;
printf_permutation(n,A,cur+1); //递归处理下一个元素(位子)
}
}
}
int main()
{
int n=3;
int A[7];
printf_permutation(n,A,0);
return 0;
}
同样的方法,把处理下标改为处理数组:
//生成p[n]的全排列
#include<stdio.h>
void printf_permutation(int n,int P[],int A[],int cur)
{
int i,j;
if(cur == n)
{
for(i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
}
else
for(i=1;i<=n;i++)
{
int ok =1;
for(j=0;j<cur;j++)
if(A[j] == P[i]) ok=0; //在这种情况下,当P[]中有重复的数时,问题就出现了!!
if(ok)
{
A[cur] = P[i];
printf_permutation(n,P,A,cur+1);
}
}
}
int main()
{
int P[] = {3,6,9};
//int P[] = {1,1,1};
int n=3;
int A[7];
printf_permutation(n,P,A,0);
return 0;
}
思想是 数序列中i个个数c2,和已生成序列中i的个数c1,如果c1<c2,则 i还可以再用用。
//生成1~n的全排列,适用于可重集。
#include<stdio.h>
void printf_permutation(int n,int P[],int A[],int cur)
{
int i,j;
if(cur == n)
{
for(i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
}
else
for(i=0;i<n;i++)
if(!i||P[i]!=P[i-1])
{
int c1=0,c2=0;
for(j=0;j<cur;j++)
if(A[j] == P[i]) c1++;
for(j=0;j<n;j++)
if(P[i] == P[j]) c2++;
if(c1<c2)
{
A[cur] = P[i];
printf_permutation(n,P,A,cur+1);
}
}
}
int main()
{
int P[] = {1,1,1};
//int P[] = {1,2,3};
int n=3;
int A[7];
printf_permutation(n,P,A,0);
return 0;
}
然后是用STL中的库函数实现的方法:
//生成1~n的全排列,适用于可重集。
#include<stdio.h>
void printf_permutation(int n,int P[],int A[],int cur)
{
int i,j;
if(cur == n)
{
for(i=0;i<n;i++)
printf("%d ",A[i]);
printf("\n");
}
else
for(i=0;i<n;i++)
if(!i||P[i]!=P[i-1])
{
int c1=0,c2=0;
for(j=0;j<cur;j++)
if(A[j] == P[i]) c1++;
for(j=0;j<n;j++)
if(P[i] == P[j]) c2++;
if(c1<c2)
{
A[cur] = P[i];
printf_permutation(n,P,A,cur+1);
}
}
}
int main()
{
int P[] = {1,1,1};
//int P[] = {1,2,3};
int n=3;
int A[7];
printf_permutation(n,P,A,0);
return 0;
}
给个小练习
地址:http://www.nowcoder.com/ta/coding-interviews?query=&asc=true&order=&page=2
字符串的排列
- 参与人数:2770时间限制:1秒空间限制:32768K
- 算法知识视频讲解
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 结果请按字母顺序输出。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> pailie;
if(str == "") return pailie;
sort(str.begin(),str.end());
do{
pailie.push_back(str);
}while(next_permutation(str.begin(),str.end()));
return pailie;
}
};
不用库函数的方法:
class Solution {
public:
vector<string> pailie;
void push_back_permutation(int n,string src,string des,int cur){
int i,j;
if(cur == n){
pailie.push_back(des);
}
else{
for(i=0;i<n;i++)
if(!i || src[i]!=src[i-1]){
int c1=0,c2=0;
for(j=0;j<cur;j++)
if(des[j] == src[i]) c1++;
for(j=0;j<n;j++)
if(src[i] == src[j]) c2++;
if(c1<c2){
des[cur] = src[i];
push_back_permutation(n,src,des,cur+1);
}
}
}
}
vector<string> Permutation(string str) {
if(str == "") return pailie;
int n = str.length();
string a(str);
sort(str.begin(),str.end());
push_back_permutation(n,str,a,0);
return pailie;
}
};