《剑指offer》面试题28
题目: 输入一个字符串,打印该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab、cba。
分析: 当我看到这个题目,我首先想到字符串中字符有可能重复,这时候该怎么办,如果没有重复那就是将所有字符的排列打印出来,全排列也是不怎么好求的,再往下就不好想了;
书中用了分治的思想,将大问题分解为小问题。此题中将一个字符串分解为两部分,第一部分为它的第一个字符,第二部分为后面的所有字符。
求一个字符串的全排列,可以分两步:首先求出所有可能出现在第一个位置的字符,在字符串中可以采用把第一个字符与后面的所有字符交换的方法,如abc字符串中a分别于b、c交换,第一个位置的字符可能是a、b、c;第二步固定第一个字符,求后面字符的排列。如此递归,直到后面的字符为字符串尾。
但是,书上的思路并没有考略字符串中字符重复的问题,如字符串aaa,按照上述思路,排列有6种,但实际上每种都是aaa,所以应该是只有一种。
因此上述思路在我看来不是完全准确的,当把第一个字符与后面的字符交换时,首先应该判断两者是否相同,如果相同则跳过,因为已经处理过此种情况。
但是这个思路同样是有问题的,如aabb,还是会出现重复的情况。。对于解决重复没有想到什么好方法。。。
所以还是默认全排列就是所有字符不管是否相同的全排列。
代码:
在函数中pStr指向整个字符串的第一个字符串,pBegin指向当前我们做排列操作的字符串的第一个字符。每一次递归从pBegin向后扫描每一个字符,交换两者后,再对pBegin后面的字符串递归地做排列操作。
void Permutation(char* pStr) { if(pStr == NULL) return; Permutation(pStr, pStr); } void Permutation(char* pStr, char* pBegin) { if(*pBegin == ‘\0‘) { printf("%s\n", pStr); } else { for(char* pCh = pBegin; *pCh != ‘\0‘; ++ pCh) { if( pCh == pBegin ) { Permutation(pStr, pBegin + 1); continue; } /*if( *pCh == *pBegin ) //去除和第一个字符相同的 { continue; }*/ char temp = *pCh; *pCh = *pBegin; *pBegin = temp; Permutation(pStr, pBegin + 1); temp = *pCh; *pCh = *pBegin; *pBegin = temp; } } }
原文:http://blog.csdn.net/kuaile123/article/details/20358445