字符串全排列和组合算法

打印字符串的全排列

算法的思路:

把一个字符串分成两部分,第一个字符+后面部分所有的字符。这样就能够递归的求解整个过程了:

1.每个字符都做一次首字符
2.当某个字符作为首字符的时候,求后面所有字符的全排列

而这里的求后面所有字符的全排列可以看成递归的子问题

全排列的递归树:

《字符串全排列和组合算法》

《字符串全排列和组合算法》

但是这里还有一个问题,那就是字符串中有重复的字符时,这样的算法会增加最后的结果数目。比如说字符串aab,a+ab的全排列,然后交换还是a+ab的全排列。所以会增加结果的数目。解决方案就是:当遇到重复的字符的时候就跳过去,不在进行递归。

所以代码实现:

#include <iostream>
#include <algorithm>
using namespace std;

void getPermutation(char *pStr, char *pBegin);
void Permutation(char *pStr);

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

void getPermutation(char *pStr, char *pBegin)
{
	if (*pBegin == '\0')
	{
		printf("%s\n", pStr);
	}
	else
	{
		for (char *pCh = pBegin; *pCh != '\0'; ++pCh)
		{
			//如果是相同的字符,那么就不用在递归,防止产生多余的字符串结果
			if (*pCh == *pBegin && pCh != pBegin)
				continue;

			swap(*pCh, *pBegin);
			getPermutation(pStr, pBegin + 1);
			swap(*pCh, *pBegin);
		}
	}
}//getPermutation

int main()
{
	char str[] = "aab";
	//这里实参如果是char *str = "abc";是不可行的,因为常量字符串是不能交换的
	Permutation(str);
	
	return 0;
}

这是C语言版的实现,再看C++版本的实现:

vector<string> Permutation(string str) 
{
	vector<string> res;
	if(str.size() == 0)
		return res;

	getPermutation(res, str, 0);

	sort(res.begin(), res.end());
	return res;
}

void getPermutation(vector<string>& res, string& str, int begin)
{
	if(begin == str.size()) 
	{
		res.push_back(str);
	}
	else
	{
		for(unsigned int i = begin; i < str.size(); i++)
		{
			if(str[i] == str[begin] && i != begin)
				continue;
			swap(str[i], str[begin]);
			getPermutation(res, str, begin + 1);
			swap(str[i], str[begin]);
		}//for
	}
}//getPermutation

  

 

    原文作者:stemon
    原文地址: https://www.cnblogs.com/stemon/p/4884122.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞