题目描述
输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串abc, acb, bac, bca, cab, cba。
题目分析
穷举与递归
又是一个经典问题,最容易想到的解决方法仍然是穷举(我实在是太爱穷举法了,每当被问到算法问题不知道如何解决的时候,总可以祭出穷举大旗,从而多争取3分钟的思考时间)。穷举虽好,但它大多数情况下都不是被需要的那个答案,是因为看起来代码太Low不够高大上吗?
在这种情况下,穷举法裹着貂皮大衣的亲戚——递归就出现了。虽然空间复杂度和时间复杂度没有任何改进,而且还增加了系统开销(关于递归法的系统开销不在这里讨论,之后再找专门的时间阐述),但是就是因为长得好看(代码看起来精炼),递归的B格儿就高了很多。
递归法对于这个题目同样非常适用,基本思路就是固定一个字符,然后对剩余的字符做全排列……不赘述,请自己想。如果你也跟我一样永远想不明白递归,那就画画图,写写代码,debug一下,每天花3-4个小时,静下心来仔细捉摸,总(ye)会(bu)想(hui)明白的。贴一段July和他伙伴们在《程序员编程艺术:面试和算法心得》中的代码实现,供做噩梦时使用。p.s. 我已加了注释
/*
* Permute full array of input string by general recusion
* @ char* perm [in/out] The string need to do permutation
* @ int from [in] The start position of the string
* @ int to [in] The end position of the string
*/
void CalcAllPermutation(char* perm, int from, int to)
{
if (to <= 1)
{
return;
}
if (from == to)
{
//all characters has been permuted
for (int i = 0; i <= to; i++)
cout << perm[i];
cout << endl;
}
else
{
// always select one character, then full array the left ones.
for (int j = from; j <= to; j++)
{
swap(perm[j], perm[from]); //swap the selected character to the beginning of string
CalcAllPermutation(perm, from + 1, to);