字符串全排列(递归与非递归)

    输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 结果请按字母顺序输出。
    递归方法:我们按照字典序列打印字符串的全排列,首先要对该字符串按照字典顺序进行排序。每次递归时,都要把当前字符和当前字符之后的所有字符进行交换(包括当前字符),需要注意的是:当递归完成以后,需要把交换过的字符串交换回来。如果字符串中有重复的字符,我们就从第一个字符起每个字符分别与它后面非重复出现的字符交换。代码如下:
void helper(string &str, int start, vector<string> &res)
{
	if (start == str.size())
	{
		res.push_back(str);
	}
	else
	{
		for (int i = start; i < str.size(); ++i)
		{
			bool flag = true;
			for (int j = i + 1; j < str.size(); ++j)
			{
				if (str[j] == str[i])
				{
					flag = false;
				}
			}
			if (flag)
			{
				swap(str[start], str[i]);
				helper(str, start + 1, res);
				swap(str[start], str[i]);
			}
		}
	}
}

vector<string> Permutation(string str)
{
	vector<string> res;
	if (str.empty())
		return res;
	helper(str, 0, res);
	sort(res.begin(), res.end());
	return res;
}

非递归方法:我们可以写一个函数,该函数的功能是求出该字符串的下一个排列,比如说字符串"abc",它的下一个排列是"acb"。如果当前字符串没有下一个排列,我们返回false。该函数的实际上就是标准库中的next_permutation算法,在我之前的文章中介绍过如何自己实现 next_permutation。在这里就不在重复叙述。代码如下:
bool nextPermutation(string& nums) 
{
	if (nums.size() < 2)
		return false;
	int pos = nums.size() - 2;
	while (pos >= 0)
	{
		if (nums[pos] >= nums[pos + 1])
		{
			pos--;
		}
		else
		{
			break;
		}
	}
	if (pos == -1)
		return false;
	char val = nums[pos];
	int i = nums.size() - 1;
	for (; i > pos; --i)
	{
		if (nums[i] > val)
			break;
	}
	swap(nums[i], nums[pos]);
	int start = pos + 1;
	int last = nums.size() - 1;
	while (start < last)
	{
		swap(nums[start++], nums[last--]);
	}
	return true;
}

vector<string> Permutation(string str)
{
	vector<string> res;
	if (str.empty())
		return res;
	sort(str.begin(), str.end());
	res.push_back(str);
	while (nextPermutation(str))
	{
		res.push_back(str);
	}
	return res;
}

猜你喜欢

转载自blog.csdn.net/yang20141109/article/details/52016523