字符串全排列
给定一组互不相同的字符,求这组字符的全排列。
输入:
输入一个字符串
ABC
输出:
输出该字符的全排列,排列的先后顺序不影响结果。
ABC ACB BAC BCA CAB CBA
思路:
只需考虑让每一个字符都做首字符的可能,然后其子串也是如此。
代码
#include<stdio.h>
#include<string.h>
char str[1000];
void Swap(char *a,char *b)
{
char temp=*a;
*a=*b;
*b=temp;
}
void solve(int from,int to)
{
if(from==to)//递归边界;
{
printf("%s ",str);
return;
}
for(int i=from;i<=to;i++)
{
Swap(&str[from],&str[i]);//首字符的排列排完后,换下一个字符做首字符
solve(from+1,to);//递归处理子串的全排列
Swap(&str[from],&str[i]);//每一个首字符排列完后,交换回来。
}
}
int main()
{
scanf("%s",&str);
int len=strlen(str);
solve(0,len-1);
return 0;
}
如果改变一下题目,输入一个可重复的字符串。
我们只需考虑,首字符下一次不能重复。加一个判断条件即可。
代码
#include<stdio.h>
#include<string.h>
char str[1000];
void Swap(char *a,char *b)
{
char temp=*a;
*a=*b;
*b=temp;
}
bool judge(int from,int to)//判断有没有重复数字打头
{
for(int i=from;i<to;i++)
{
if(str[i]==str[to])
{
return false;
}
}
return true;
}
void solve(int from,int to)
{
if(from==to)//递归边界;
{
printf("%s\n",str);
return;
}
for(int i=from;i<=to;i++)
{
if(judge(from,i))
{
Swap(&str[from],&str[i]);//首字符的排列排完后,换下一个字符做首字符
solve(from+1,to);//递归处理子串的全排列
Swap(&str[from],&str[i]);//每一个首字符排列完后,交换回来。
}
}
}
int main()
{
scanf("%s",&str);
int len=strlen(str);
solve(0,len-1);
return 0;
}
这个算法的复杂度为(n+1)!的,本题可以用空间换时间,转化为n!。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1e5;
char str[MAXN];
void solve(int from,int to)//解决重复数字问题。用空间换时间
{
if(from==to)//递归边界
{
printf("%s\n",str);
return;
}
int mask[256]={};
for(int i=from;i<=to;i++) mask[str[i]]=0;
for(int i=from;i<=to;i++)
{
if(mask[str[i]]==1) continue;
mask[str[i]]=1;
swap(str[from],str[i]);
solve(from+1,to);
swap(str[from],str[i]);
}
}
int main()
{
scanf("%s",&str);
int len=strlen(str);
solve(0,len-1);
return 0;
}