递归解决全排列问题+详细图解递归执行


问题描述:字符串的排列

//输入一个字符串, 按字典序打印出该字符串中字符的所有排列。
//例如输入字符串abc, 则打印出由字符a, b, c所能排列出来的所有字符串abc, acb, bac, bca, cab和cba。
//结果请按字母顺序输出。
//长度不超过9(可能有字符重复), 字符只包括大小写字母。


分析:

采用分治法,把一个字符串看成两部分:第一部分是它的第一个字符,第二部分是后面的所有字符。

(1)首先求所有可能出现在第一个位置的字符,也就是把第一个字符和后面的所有字符交换;


(2)把后面的字符串看成一个新的字符串,重复上面步骤。


代码:

void PermutationLocal(string str, vector<string>& ret, int index)
{
	if (index == str.length()-1)  //一次递归结束条件
	{
		ret.push_back(str);
	}

	else
	{
		for (size_t i = index; i < str.length(); ++i)
		{
			if(i != index && str[i] == str[index])
			{
				continue;
			}

			//std:swap(str[i], str[index]);     //交换
			char tmp = str[i];
			str[i] = str[index];
			str[index] = tmp;

			PermutationLocal(str, ret, index + 1);
		}
	}
}
vector<string> Permutation(string str) 
{
	vector<string> ret;
	int index = 0;
	if (!str.empty())
	{
		PermutationLocal(str, ret, index);
	}
	return ret;
}

测试:

void main()
{
	vector<string> v;
	v = Permutation("abc");

	for(auto i : v)
		cout << i.c_str() << endl;
}


递归详解(调试图解):

(1)递归初始化:


(2)第一次PermutationLocal:


(3)第二次PermutationLocal:


如上图,index = 2,本次递归将要结束,

ret插入了值。


(4)随后本次递归被抛出栈,直接跳转到上次递归的“”断点“”,开始继续执行。其实我觉得理解递归,重点、关键是要理解“函数栈”、“保存函数断点”、“返回函数断点”!



后面步骤不再截图赘述,请自行调试、观察数据变化、堆栈变化、执行流程。

阅读更多

没有更多推荐了,返回首页