字符串的组合与排列 - 递归实现

题目:输入一个字符串,输出该字符串中字符的所有组合。举个例子,如果输入abc,它的组合有abcabacbcabc

分析:递归实现,根据组合公式C(n,k) = C(n-1,k) + C(n-1,k-1), 如果我们想要在长度为n的字符串中求k个字符的组合,首先选择第一个字符,对余下n-1个字符可以分为两个部分进行求解:

(1)当前组合中包含当前字符,那么只需要在剩下的n-1个字符中选择k-1个字符,组成k个字符的组合。

(2)当前组合中不包含当前字符,那么就需要在剩下的n-1个字符中选择k个字符,组成k个字符的组合。

递归源码:

/*
	输入一个字符串,输出该字符串中字符的所有组合。
	举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。
*/
void Combination(char* str, int num, vector<char>& result)
{
	// 处理完最后一个字符,结束
	if(*str=='\0')
		return;

	// num个字符的某个序列已经选取完,输出之
	if(num==0)
	{
		vector<char>::iterator iter = result.begin();
		for (; iter != result.end(); ++iter)
		{
			cout<<*iter;
		}
		cout<<endl;
		return;
	}

	// num-1个字符的组合中包括当前字符,在剩下的串中选取num-1个字符的序列
	result.push_back(*str);
	Combination(str+1, num-1, result);
	result.pop_back();

	// num个字符的组合中不包括当前字符,在剩下的串中选取num个字符的序列
	Combination(str+1, num, result);
}

void Combination(char* str)
{
	if(!str) return;

	int n = strlen(str);
	vector<char> result;
	for (int i = 0; i < n; ++i)
	{
		Combination(str, i+1, result);
	}
}
 
如果要求的某一特定的组合,只需将函数中的for循环去掉,将i制定为你所求的特定值即可。

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

分析:我们首先以abc三个字符组成的字符串为例,分析其全排列的过程。

(1)固定第一个字符a,求后面两个字符bc的排列。

(2)将字符a和字符b交换,得到bac。固定第一个字符b,求后面两个字符ac的排列。

(3)现在需要将字符c放在第一个位置,固定第一个字符c。在(2)中我们已经将字符a和字符b交换了,为了保证字符c仍然是和初始时的第一个字符a交换,需要先将字符b和字符a交换回来,然后再将c和第一个位置的字符a交换,得到cba。固定第一个字符c,求后面两个字符ba的排列。

不难扩展到n个字符:

设n个字符的字符串S的全排列为Permutation(S);  设Si为不包括第i个字符,其它n-1个字符组成的字符串。(Si)Permutation(Si)表示第一个字符为Si的全排列。

当n>1时,字符串的全排列Permutation(S) 由(S1)Permutation(S1), (S2)Permutation(S2),...,(Sn)Permutation(Sn)构成。

当n=1时,字符串中只包括一个元素,不再需要排列,递归结束。


递归源码:

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

void swap(char* a, char* b)
{
	char tmp;
	tmp = *a;
	*a = *b;
	*b = tmp;
}

void Permutation(char* str, int i, int n)
{
	// 当前需要处理的元素只有最后一个的时候,表示处理结束,输出当前排列。
	if(i == n)
		printf("%s\n", str);
	else
	{
		for (int j = i; j <= n; ++j)
		{
			//为避免生成重复排列,当不同位置的字符相同时不再交换 
			if(str[i] == str[j] && j != i)
				continue;

			swap(str+i, str+j);
			Permutation(str, i+1, n);
			swap(str+i, str+j);
		}
	}
}

/
// Get the permutation of a string, 
// for example, input string abc, its permutation is 
// abc acb bac bca cba cab
/
void Permutation(char* str)
{
	if(!str)
		return;

	Permutation(str, 0, strlen(str)-1);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值