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

<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",它的组合有abcabacbcabc

      本题也可以用递归的思路来求字符串的组合。      假设我们想在长度为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 == '\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>



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值