Problem
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.
For example:
Given s = “
aabb
“, return["abba", "baab"]
.Given s = “
abc
“, return[]
.
Solution
- 判断回文
先判断能否生成回文数,条件是所有的char都出现偶数次,如果有奇数次的char,必须只能有一个。否则就无法构成回文。 - 构造回文
可以只构造前半部分,就是一个构造排列组合的过程。这里有一个技巧,比如有字符串aa,那么当我们要使用第二个a的时候,必须确保第一个a已经被使用了,这样就能有效避免重复的回文出现。另外如果有基数的char,那么必定出现在整个字符串的中间。
class Solution {
private:
map<char, int> count;
vector<char> chars;
vector<bool> canUse;
vector<string> ret;
string result;
char oddChar;
int oddNum = 0;
public:
void generate(int dep, int maxDep) {
if (dep == maxDep) {
if (oddNum > 0) {
result[dep] = oddChar;
}
int j = result.size() - 1;
for(int i = 0; i < maxDep; i++) {
result[j] = result[i];
j--;
}
ret.push_back(result);
return;
}
for(int i = 0; i < maxDep; i++) {
if (canUse[i]) {
if (i != 0 && chars[i] == chars[i-1] && canUse[i-1]) {
continue;
}
result[dep] = chars[i];
canUse[i] = false;
generate(dep + 1, maxDep);
canUse[i] = true;
}
}
}
vector<string> generatePalindromes(string s) {
for(int i = 0; i < s.size(); i++) {
count[s[i]]++;
}
// check if it is valid
for(map<char, int>::iterator iter = count.begin(); iter != count.end(); iter++) {
if (iter->second % 2 == 1) {
oddNum++;
oddChar = iter->first;
}
for(int i = 0; i < iter->second / 2; i++) {
chars.push_back(iter->first);
}
}
if (oddNum >= 2) {
return ret;
}
canUse.resize(chars.size());
for(int i = 0; i < canUse.size(); i++) {
canUse[i] = true;
}
result = s;
generate(0, chars.size());
return ret;
}
};