一、字符串的排列
给定一个字符串,如何求出字符串的所有排列。
解题思路:字符串的排列可以拆分成,第一个字符和后面的字符进行组合而成,只需要变换第一个字符,然后递归求后面的字符的排列即可,等到后面的字符为空的时候就得到一种字符的排列,下面是代码实现:
// str 要排列的字符串
// pBegin 待排列的字符串的起始位置,递归用
void Permutation(char *str, char *pBegin)
{
// 如果待排列的字符串为空,即起始位置为'\0',则得到一种排列,打印
if (*pBegin == '\0')
printf("%s\n", str);
else // 否则遍历字符串,分别和第一个字符进行换位置,然后递归排列后面的字符
{
for (char *pCh = pBegin; *pCh != '\0'; ++pCh)
{
char temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
Permutation(str, pBegin + 1);
// 排列完成后还原位置
temp = *pCh;
*pCh = *pBegin;
*pBegin = temp;
}
}
}
// 外部函数
void Permutation(char *str)
{
if (str == NULL)
return;
Permutation(str, str);
}
二、字符串的组合
如何求字符串的所有组合,组合和排列不同,例如:"abc"的组合有"a"、“b”、“c”、“ab”、 “ac”、“bc”和“abc”。
解题思路:对于一个长度为n的字符,它的组合长度有1位、2位、3位...n位,可以用循环分别求1-n位的组合,对于m位的组合可以拆分成取第一位,然后从后面的n-1位取m-1位组成一个组合,或者不取第一位,然后从后面的n-1位取m位组成一个组合,形成一个递归算法,代码如下:
// 递归求iNum位的所有组合
// pStr 要求组合的字符串
// iNum 组合的位数
// result 保存组合
void Combination(char *pStr, int iNum, std::vector<char> &result)
{
// 如果字符串为空,或者要求组合的位数不为0且字符串为空,则不可能生成组合
if (pStr == NULL || (iNum != 0 && *pStr == '\0'))
return;
// 如果要求组合的位数为0,表示已生成组合,则打印组合
if (iNum == 0)
{
std::vector<char>::iterator it;
for (it = result.begin(); it != result.end(); ++it)
{
printf("%c", *it);
}
printf("\n");
}
else
{
// 否则取第一个字符作为组合第一位,从剩下n-1位,取iNum - 1个字符得到组合
result.push_back(*pStr);
Combination(pStr + 1, iNum - 1, result);
// 另一种情况,不取第一位,从剩下的n-1位,取iNum个字符得到组合
result.pop_back();
Combination(pStr + 1, iNum, result);
}
}
// 外部函数,分别求1-n位的所有组合
void Combination(char * str)
{
int n = strlen(str);
std::vector<char> result;
for (int i = 1; i <= n; i++)
{
Combination(str, i, result);
}
}