问题描述:字符串的排列
//输入一个字符串, 按字典序打印出该字符串中字符的所有排列。
//例如输入字符串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)随后本次递归被抛出栈,直接跳转到上次递归的“”断点“”,开始继续执行。其实我觉得理解递归,重点、关键是要理解“函数栈”、“保存函数断点”、“返回函数断点”!
后面步骤不再截图赘述,请自行调试、观察数据变化、堆栈变化、执行流程。