题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
思想:复杂问题分解成小的问题,比如可以把一个字符串看成两部分组成,第一部分是它的第一个字符,第二部分是后面的所有字符。所以求整个字符串的排列,可以看成两步。第一步求出所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换;第二步固定第一个字符,求后面所有字符的排列,仍把后面的所有字符分成两部分:后面字符的第一个字符,以及这个字符之后的所有字符,然后把第一个字符逐一和它后面的字符交换。典型的递归思想!
代码:
class Solution {
public:
vector<string> Permutation(string str) {
if(str.length() == 0)
return result;
PermutationHelp(str,0);
//对结果进行排序
sort(result.begin(),result.end());
return result;
}
void PermutationHelp(string str,int begin){
//递归的条件,第一位和最后一位交换完毕
if(begin == str.length()){
result.push_back(str);
return;
}
for(int i = begin;i<str.length();i++){
//如果字符串相同,则不交换
if(i != begin && str[i] == str[begin]){
continue;
}
//位置交换
swap(str[begin],str[i]);
//递归,固定前面begin+1的字符不变,后面的字符串全排列
PermutationHelp(str,begin+1);
}
}
vector<string> result;
};
剑指offer的讨论区的参考代码(仍有不懂的地方):
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> ans;
PermutationHelp(ans,0,str);
return ans;
}
void PermutationHelp(vector<string> &ans,int k,string str){
if(k == str.size()-1)
ans.push_back(str);
unordered_set<char> us;
sort(str.begin()+k,str.end());
for(int i = k; i<str.size();i++){
if(us.find(str[i])== us.end()){
us.insert(str[i]);
swap(str[i],str[k]);
PermutationHelp(ans,k+1,str);
swap(str[i],str[k]);
}
}
}
};