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;
}
};