您的位置:首页 > 其它

(1)字符串全排列 / 组合

2013-11-01 20:13 288 查看
题目描述:输入一个字符串,打印出该字符串的全部排列;

例如:字符串:abc     全排列:(abc , acb) , (bac , bca) , (cba , cab);

解题思路:

递归实现:从字符串中“依次”选择一个字符作为“首字符”,并在该“首字符”前提下,对剩余字符进行递归全排列处理;

“依次”:即始终在“初始字符串”的前提下,后面的字符分别于第一个字符交换;

字符串abc:

(abc)首字符a-->求剩余bc全排列:abc , acb;-->(a,b)交换-->bac;

(bac)首字符b-->求剩余ac全排列:bac , bca;-->(a,b)交换-->abc(以便在此基础上得到cba)-->(a,c)交换-->cba;

(cba)首字符c-->求剩余ba全排列:cba,cab;

算法递归实现:

#include<iostream>
using namespace std;
//------------------------------------------------------------------------------------------------------------------
void  Permutation(char* pStr , char* pBegin);
void  Swap(char *ch1 , char *ch2);
//-------------------------------------------------------------------------------------------------------------------
void  Swap(char *ch1 , char *ch2)
{
char temp = *ch1;
*ch1 = *ch2;
*ch2 = temp;
}

//不能保证出现重复排列。
void Permutation(char* pStr , char* pBegin)
{
if(*pBegin == '\0')
{
printf("%s\n" , pStr);
}
else
for(char* pch = pBegin; *pch != '\0'; ++pch)
{
Swap(pch , pBegin);
Permutation(pStr , pBegin + 1);
Swap(pch , pBegin);
}
}

void Permutation(char* pStr)
{
if(pStr == NULL)
return ;

Permutation(pStr , pStr);
}

但是若字符串中出现重复的字符,两者交换。全排列中会出现重复的结果。这样不仅加大工作量,而且还是没有意义的,故应该去掉重复的全排列结果。

怎么去除呢?

规则:从首字符起,每个字符依次与后面不重复的字符交换。

例子:字符串abb;

(abb)首字符a-->求剩余全排列:abb-->(b,b)相等不交换;-->(a,b)交换bab;

(bab)首字符b-->求剩余全排列:bab , bba;-->(b,a)交换abb-->由于二三字符b ,b 相同,故a不再与第三个字符交换,结束;

代码实现:

#include<iostream>
using namespace std;
//------------------------------------------------------------------------------------------------------------------------
bool IsSwap(char* pBegin , char* pEnd);           //判断是否有字符相等
void Permutation(char* pStr , char *pBegin);
//------------------------------------------------------------------------------------------------------------------------
void Permutation(char* pStr)
{
if(!pStr)
return;

Permutation(pStr , pStr);
}

//在[nBegin,nEnd)区间中是否有字符与下标为pEnd的字符相等
bool IsSwaped(char* pBegin , char* pEnd)
{
char *S;
for(S = pBegin ; S < pEnd ; S++)
{
if(*S == *pEnd)
return false;
}
return true;
}

void Permutation(char* pStr , char *pBegin)
{

if(*pBegin == '\0')
{
printf("%s\n",pStr);
}
else
{
//依次与首字符交换,固定。剩余递归进行全排列
for(char *pCh = pBegin; *pCh != '\0'; pCh++)
{
if(IsSwaped(pBegin , pCh))
{
swap(*pBegin , *pCh);
Permutation(pStr , pBegin + 1);
swap(*pBegin , *pCh);
}
}
}
}


字符串的组合问题:

问题描述:给定一个字符串,求该字符串中所有字符的组合;例如abc,所求组合为:a , b , c , ab , ac , bc , abc;

长度为n的字符串,选取m个字符的组合,其中1 <= m <= n;

设总组合数为Comb(n , m) = Comb(n , 1) + Comb(n , 2) + Comb(n , 3) + ......+ Comb(n , n);

递归求解

从首字符开始扫描,若被选中,则递归求解:Comb(n - 1 , m - 1);

                                 若未被选中,则递归求解:Comb(n - 1 , m);

递归终止条件: n = 0  或者  m = 0;

代码实现:

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
//------------------------------------------------------------------------------------------------------------------
void Combination(char* pStr , int m , vector<char>& result);
//-------------------------------------------------------------------------------------------------------------------
//函数功能:求一个字符串的所有组合
//参数:字符串pStr
void Combination(char* pStr)
{
if(pStr == NULL)
return;

vector<char> result;
int length = strlen(pStr);

for(int i = 1; i <= length; i++)
Combination(pStr , i , result);
}

//函数功能:从一个字符串中选取m个字符
//参数:字符串pStr ,选取元素个数m , 存放结果result
void Combination(char* pStr , int m , vector<char>& result)
{
if(pStr == NULL || (*pStr == '\0' && m != 0))
return;

//递归终止条件
if(m == 0)
{
vector<char>::iterator  iter = result.begin();
for( ; iter != result.end(); iter++)
cout<<*iter<<' ';
cout<<endl;

return;     //注意
}

//选中此元素
result.push_back(*pStr);
Combination(pStr + 1 , m - 1 , result);
result.pop_back();

//未选中此元素
Combination(pStr + 1 , m , result);

}

//----------------------------------------------------------------------------------------------------------------
int main()
{
char string1 [] = " ";
Combination(string1);

char string2[] = "accd";
Combination(string2);

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