题目:
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 []
.
思路:
由于是需要得到所有符合要求的答案,所以很自然的可以想到BackTracking。思路是:首先判断是否可以构成合法的回文数(用Palindrome Permutation I的思路),如果无法构成,则返回。否则,如果有一个字符出现了奇数次,则把它首先放在字符串的最中间。然后再用类似于DFS的方法,依次从0到s.length() / 2 - 1放置当前哈希表中还剩余的字符(对于回文串而言,一旦前一半的字符确定了,则后一半的字符也必然确定无疑了)。最关键的一步是,调用下一层的DFS之后,记得恢复计数,这样在尝试下一个字符的时候,计数器才是正确的。
代码:
class Solution {
public:
vector<string> generatePalindromes(string s) {
vector<string> ret;
string line(s);
unordered_map<char, int> hash;
for (auto val : s) {
++hash[val];
}
int odd_num = 0;
char odd_char = ' ';
for (auto it = hash.begin(); it != hash.end(); ++it) {
if (it->second % 2 != 0) {
++odd_num;
odd_char = it->first;
}
}
if (odd_num > 1) {
return {};
}
else if (odd_num == 1) {
line[s.length() / 2] = odd_char;
--hash[odd_char];
}
generatePalindromes(ret, line, 0, hash);
return ret;
}
private:
void generatePalindromes(vector<string> &ret, string &line, int index,
unordered_map<char, int> &hash) {
int length = line.length();
if (index == length / 2) {
ret.push_back(line);
return;
}
for (auto it = hash.begin(); it != hash.end(); ++it) {
if (it->second > 0) {
line[index] = line[length - 1 - index] = it->first;
it->second -= 2;
generatePalindromes(ret, line, index + 1, hash);
it->second += 2;
}
}
}
};