您的位置:首页 > 其它

求字符串中字符全排列 和 组合

2015-09-25 15:01 232 查看
<span style="font-size:18px;">(1)若不考虑字符串中有重复字符(即假设字符串中无重复字符)
(2)若考虑字符串中有重复字符(即假设字符串中有重复字符)

<br style="" /></span>
(2)若考虑字符串中有重复字符(即假设字符串中有重复字符)
上述思路非常好,但是若存在重复字符,则就不正确了,比如对于上述程序,输入“aabc”,则输出:



      就会出现重复的结果。我本来思考着如果在与*pBegin交换时加一个条件语句判断是否相等,若与*pBegin相等就不交换,若不相等才交换,用“aabc”测试时结果确实正确了。但是实际上是错误的,比如用“abbc”测试时就不正确了。      我也是看到了一个网友的方法才发现我上述考虑的方法是错误的,他的方法是判断当前*pCh的字符(即准备与*pBegin交换的字符)在前面的子字符串中是否出现过了,若出现了,就不交换,若没出现就交换。代码如下:
<span style="font-size:18px;"><pre name="code" class="cpp">void Permutation(char* pSrc,  char* pBegin)
{
if (!pSrc || !pBegin)
{
return;
}

if (*pBegin == '\0')
{
printf("%s\n", pSrc);
}
else
{
for (char* pCh=pBegin; *pCh!='\0'; ++pCh)
{
if(strchr(pBegin, *pCh) == pCh)
{
char temp = *pBegin;
*pBegin = *pCh;
*pCh = temp;

Permutation(pSrc, pBegin+1);

temp = *pBegin;
*pBegin = *pCh;
*pCh = temp;
}
}
}
}

int main()
{
char pSrc[] = "abbc";

Permutation(pSrc, pSrc);

return 0;
}</span>


运行结果是:



二、字符串的组合
(1)若不考虑字符串中有重复字符(即假设字符串中无重复字符)
      输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入"abc",它的组合有a、b、c、ab、ac、bc、abc。
      本题也可以用递归的思路来求字符串的组合。 
    假设我们想在长度为n的字符串中求m个字符的组合。我们先从头扫描字符串的第一个字符。针对第一个字符,我们有两种选择:一是把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选取m-1个字符;而是不把这个字符放到组合中去,接下来我们需要在剩下的n-1个字符中选择m个字符。这两种选择都很容易用递归实现。下面是这种思路的参考代码:

<span style="font-size:18px;">void Combination(char* str, int number, vector<char>& result)
{
if (str==NULL)
{
return;
}

if (number==0)
{
for (vector<char>::iterator ite = result.begin(); ite!=result.end(); ++ite)
{
cout<<*ite;
}
cout<<endl;
return;
}

if (*str == '\0')
{
return;
}

else
{
Combination(str+1, number, result);

result.push_back(*str);
Combination(str+1, number-1, result);
result.pop_back();
}

}

int main()
{
char pSrc[] = "abc";

vector<char> result;
for (int i=1; i<=strlen(pSrc); ++i)
{
Combination(pSrc, i, result);
}

return 0;
}</span>


      运行结果是:



也可以去掉上述中的循环:
<span style="font-size:18px;"><pre name="code" class="cpp">void Combination(char* str, int number, vector<char>& result)
{
if(*str ==
4000
'\0')
{

for(vector<char>::iterator ite = result.begin();
ite != result.end();
++ite)
{
cout<<*ite;
}
cout<<endl;

return;
}

result.push_back(*str);
Combination(str + 1, number - 1, result);
result.pop_back();

Combination(str + 1, number-1, result);
}

int main()
{
char pSrc[] = "abc";

vector<char> result;
Combination(pSrc, strlen(pSrc), result);

return 0;
}</span>


        另外,看到一个网友的思路:用一个数组,模拟2进制加法器,某一个为1,则取对应的字符,若为0则不取,就能够实现字符组合。这个思路也非常好~ 不过是在字符长度不超过32的情况下。

(2)若考虑字符串中有重复字符(即假设字符串中有重复字符)       但是上述代码在字符串中有重复字符时就出问题了,如输入”abbc“,则输出为:



<span style="font-size:18px;">void Combination(char* str, int number, vector<char>& result)
{
if (str==NULL)
{
return;
}

if (number==0)
{
for (vector<char>::iterator ite = result.begin(); ite!=result.end(); ++ite)
{
cout<<*ite;
}
cout<<endl;
return;
}

if (*str == '\0')
{
return;
}

else
{
Combination(str+1, number, result);

result.push_back(*str);
Combination(str+1, number-1, result);
result.pop_back();
}

}

int main()
{
char pSrc[] = "abc";

vector<char> result;
for (int i=1; i<=strlen(pSrc); ++i)
{
Combination(pSrc, i, result);
}

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