【剑指Offer-分解让复杂问题简单化】面试题38:字符串的排列
题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
牛客网输入:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
注:牛客网的输入可能有字符重复,而书上是没有重复字符的。
思路1
可以模拟人来做排列的情形,比如3个字符a、b和c。第一个字符有3种选择:a、b或者c,当第一个字符确定之后,第二个字符有2种选择,当前两个字符确定之后,最后一个字符也确定了。使用循环和递归来模拟这一过程,代码如下:
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> ans;
if(str=="")
return ans;
int visit[str.length()];
memset(visit, 0, sizeof(visit));
string cur;
PermutationCore(str, ans, cur, visit);
ans = RemoveRepeat(ans);
return ans;
}
void PermutationCore(string str, vector<string>& ans, string cur, int* visit){
if(cur.length()==str.length()){
ans.push_back(cur);
return;
}
for(int i=0; i<str.length(); i++){
if(!visit[i]){
visit[i] = 1;
cur+=str[i];
PermutationCore(str, ans, cur, visit);
cur = cur.substr(0, cur.length()-1); //把前一步加的字符删掉
visit[i] = 0;
}
}
}
vector<string> RemoveRepeat(vector<string> ans){
set<string> s;
for(int i=0; i<ans.size(); i++)
s.insert(ans[i]);
vector<string> newAns;
for(set<string>::iterator it=s.begin();it!=s.end(); it++)
newAns.push_back(*it);
return newAns;
}
};
由于牛客网的输入可能包含重复数字,最终的输出中也包含重复的排列,所以添加了一个去重的函数RemoveRepeat,去重的思路是将所有排列放到set中,set中的元素都是唯一的,然后再把set中的元素放到vector中返回。
思路2
第2个思路就是书上的方法,将求整个字符串的排列分为2步:第一求所有可能出现在第一个位置的字符,也就是将第一个字符与后面所有字符交换;第二步,固定第一个字符,重复第一步的过程。代码如下:
class Solution {
public:
vector<string> Permutation(string str) {
vector<string> ans;
if(str=="")
return ans;
int cur = 0;
PermutationCore(str, ans, cur);
ans = RemoveRepeat(ans);
return ans;
}
void PermutationCore(string str, vector<string>& ans, int cur){
if(cur==str.length()){
ans.push_back(str);
return;
}
for(int i=0; i<str.length(); i++){
swap(str, i, cur);
PermutationCore(str, ans, cur+1);
swap(str, i, cur);
}
}
void swap(string& str, int a, int b){
char t = str[a];
str[a] = str[b];
str[b] = t;
}
vector<string> RemoveRepeat(vector<string> ans){
set<string> s;
for(int i=0; i<ans.size(); i++)
s.insert(ans[i]);
vector<string> newAns;
for(set<string>::iterator it=s.begin();it!=s.end(); it++)
newAns.push_back(*it);
return newAns;
}
};