剑指Offer:面试题28 字符串的排列

/*
字符串的排列:
输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的
所有字符串abc、acb、bac、bca、cab和cba


思路:
可以先对字符串中的字符按字典序排序,然后采用递归进行输出。


书上的思路:
把一个字符串看成由两部分组成:第一部分为它的一个字符,第二部分为后面的字符。
1:先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换。
2:固定一个字符,求后面所有字符的排列。然后再把后面的字符分成2部分:后面字符的第一个字符,这个字符后面
的所有字符。


输入:
每个测试案例包括1行。
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
输出:
对应每组数据,按字典序输出所有排列。
样例输入:
abc
BCA
样例输出:




abc
acb
bac
bca
cab
cba//有问题
ABC
ACB
BAC
BCA
CAB
CBA


*/


/*
关键:
1 for(int i = 0 ; i < n ; i++)//确定大排序中第一个元素的位置
{
if(!i || str[i] != str[i-1])//确保当前元素与前面一个元素不能重复时才递归
{
int iCountPer = 0;
for(int j = 0 ; j < iPos ; j++)//统计str[i]在已经排列的数组中出现的次数
{
if(str[i] == sPer[j])
{
iCountPer++;
}
}
int iCountStr = 0;
for(int k = 0 ; k < n ; k++)//统计str[iPos]在输入数组中出现的次数
{
if(str[i] == str[k])
{
iCountStr++;
}
}
if(iCountPer < iCountStr)
{
sPer[iPos] = str[i];//把第iPos个元素确定下来之后进行后续递归
printPermutation(str,sPer,n,iPos+1);
*/


#include <stdio.h>
#include <string.h>
const int MAXSIZE = 10;


void permutationStr(char* str,char* pStart)//str指向整个字符串的第一个字符,pStart指向当前做排列操作的字符串的第一个字符
{
if('\0' == *pStart)//如果已经抵达末尾,直接输出
{
printf("%s\n",str);
}
else
{
for(char* pCh = pStart ; *pCh != '\0' ; pCh++)
{
char chTemp = *pCh;//交换其余字符与首字母
*pCh = *pStart;
*pStart = chTemp;
permutationStr(str,pStart+1);//继续递归,从pStart向后扫描每一个字符。再对pStart之后的字符串递归地做排列操作
chTemp = *pCh;//回溯法,再交换回来
*pCh = *pStart;
*pStart = chTemp;
}
}
}


void permutation(char* str)
{
if(!str)
{
return;
}
permutationStr(str,str);
}


void printPermutation(char* str,char* sPer,int n,int iPos)
{
if(iPos == n)//如果已经抵达数组末尾,则输出
{
for(int i = 0 ; i < n ; i++)
{
printf("%c",sPer[i]);
}
printf("\n");
}
else
{
for(int i = 0 ; i < n ; i++)//确定大排序中第一个元素的位置
{
if(!i || str[i] != str[i-1])//确保当前元素与前面一个元素不能重复时才递归
{
int iCountPer = 0;
for(int j = 0 ; j < iPos ; j++)//统计str[i]在已经排列的数组中出现的次数
{
if(str[i] == sPer[j])
{
iCountPer++;
}
}
int iCountStr = 0;
for(int k = 0 ; k < n ; k++)//统计str[iPos]在输入数组中出现的次数
{
if(str[i] == str[k])
{
iCountStr++;
}
}
if(iCountPer < iCountStr)
{
sPer[iPos] = str[i];//把第iPos个元素确定下来之后进行后续递归
printPermutation(str,sPer,n,iPos+1);
}
}
}
}
}




void process()
{
char str[MAXSIZE];
while(EOF != scanf("%s",str))
{
//permutation(str);
char sPer[MAXSIZE];
printPermutation(str,sPer,strlen(str),0);
}
}


int main(int argc,char* argv[])
{
process();
getchar();
return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值