Permutations without Dups:生成一个字符串的所有排列,字符串中不包含重复字符。
如果有了前n - 1
个字符的全排列,那么只要把第n
个字符依次插入到每个位置就可以了。但是在连续存储中插入字符的效率比较低,所以效果不是特别理想。
class Solution {
public:
vector<string> permutation(string S) {
Permutation(S, S.size());
return Perm;
}
private:
vector<string> Perm;
void Permutation(const string &str, size_t size)
{
if(size == 0){
Perm.push_back("");
return;
}
Permutation(str, size - 1);
char c = str[size - 1];
size_t cnt = Perm.size();
for(size_t idx = 0; idx < cnt; idx++)
{
for(size_t pos = 0; pos < size - 1; pos++)
{
const string &s = Perm[idx];
Perm.push_back(s.substr(0, pos) + c + s.substr(pos));
}
Perm[idx].push_back(c);
}
}
};
另一种方法是生成任意n - 1
个字符的所有排列,然后将没有使用的第n
个字符插入到任意位置即可,为了方便代码中选择将该字符作为第1
个字符。
class Solution {
public:
vector<string> permutation(string S) {
Permutation(S);
return Perm;
}
private:
vector<string> Perm;
string res;
void Permutation(const string &str)
{
if(str.empty()){
Perm.push_back(res);
return;
}
for(size_t i = 0; i < str.size(); i++)
{
res.push_back(str[i]);
Permutation(str.substr(0, i) + str.substr(i + 1));
res.pop_back();
}
}
};
我记得当年上课的时候,老师讲的是一种依次交换的算法,这种方法基本没有额外的空间开销,而且只有这种方法和力扣上标准输出的顺序是一样的。
class Solution {
public:
vector<string> permutation(string S) {
Permutation(S, 0);
return Perm;
}
private:
vector<string> Perm;
void swapChar(char &c1, char &c2)
{
char c = c1;
c1 = c2;
c2 = c;
}
void Permutation(string &str, const size_t curr)
{
if(curr == str.size()){
Perm.push_back(str);
return;
}
for(size_t idx = curr; idx < str.size(); idx++)
{
swapChar(str[curr], str[idx]);
Permutation(str, curr + 1);
swapChar(str[curr], str[idx]);
}
}
};