267. Palindrome Permutation II
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.
Example 1:
Input: “aabb”
Output: [“abba”, “baab”]
Example 2:
Input: “abc”
Output: []
方法1:
思路:
先用266. Palindrome Permutation判断是否可存在。如果存在,先判断是否存在奇数。根据hint,回文串只用generate一半就可以,那么传入dfs的就是一个标准的permutation问题。同时事先处理好一个mid根据奇偶数可以为空集或者单个字符,传入dfs,用Permutations II的方法来找到不重复的所有排列方式。但是这里由于用到了hashmap,去重的问题反而变得简单了,不存在顺序,只存在取用次数。permutation ii也可以采用这种方法。这里一开始尝试的是用vector,但是发现test远不止26个字母,而hashmap完全不用受到限制。
易错点
- 进入dfs前数量减半(奇数此时也被取偶)
- 所有需要修改的hash,都要用&来iterate
class Solution {
public:
vector<string> generatePalindromes(string s) {
vector<string> result;
unordered_map<char, int> hash;
string pseudo = "", mid ="";
// 计数
for (auto a: s) ++hash[a];
// 找到mid,如果有奇数,为该字符,如果没有,保持空集
for (auto & a: hash){
if (a.second % 2 == 1){
mid += a.first;
}
// 数量减半
a.second /= 2;
// 生成减半数量的字符串用于dfs
pseudo += string(a.second, a.first);
// not possible to generate palindrome
if (mid.size() > 1) return {};
}
string current ="";
dfs(pseudo, hash, result, mid, current);
return result;
}
void dfs(string & p, unordered_map<char, int> & hash, vector<string> & result, string & mid, string& current){
if (current.size() == p.size()){
result.push_back(current + mid + string(current.rbegin(), current.rend()));
return;
}
for (auto & a: hash){
if (a.second > 0){
--a.second;
string c = current + a.first;
dfs(p, hash, result, mid, c);
++a.second;
}
}
return;
}
};
方法2: dfs + swap
grandyang: http://www.cnblogs.com/grandyang/p/5315227.html
class Solution {
public:
vector<string> generatePalindromes(string s) {
unordered_set<string> result;
unordered_map<char, int> hash;
string pseudo = "", current ="";
// 计数
for (auto a: s) ++hash[a];
for (auto a: hash){
if (a.second % 2 == 1){
current += a.first;
}
pseudo += string(a.second/2, a.first);
if (current.size() > 1) return {};
}
dfs(pseudo, 0, result, current);
return vector<string> (result.begin(), result.end());
}
void dfs(string & p, int start, unordered_set<string> & result, string& current){
if (start >= p.size()){
result.insert(p + current + string(p.rbegin(), p.rend()));
return;
}
for (int i = start; i < p.size(); i++){
if (i != start && p[i] == p[start]) continue;
swap(p[i], p[start]);
dfs(p, start + 1, result, current);
swap(p[i], p[start]);
}
return;
}
};
非要自己写,丑而慢不说,没想到人家不止有26个字母吧。面试的时候不问清楚秒挂。放在这引以为戒,里面也包含一些坑:
- 如果想对hash进行修改,在遍历的时候就要用&
- 长度判断,先+1再/2
class Solution {
public:
vector<string> generatePalindromes(string s) {
vector<string> result;
if (!palindrome(s)) return {};
bool odd = false;
string current = "";
for (auto & a: hash){
if (a.second % 2 == 1){
current += a.first;
a.second--;
odd = true;
}
}
bag.resize(26, 0);
for (auto & a: hash){
while (a.second != 0){
a.second -= 2;
++bag[a.first - 'a'];
}
}
dfs(s, result, current, '0');
if (odd) {
for (string & a: result){
string r = a.substr(1);
reverse(r.begin(), r.end());
a = r + a;
}
}
else {
for (string & a: result){
string r = a;
reverse(r.begin(), r.end());
a = r + a;
}
}
return result;
}
private:
map<char, int> hash;
vector<int> bag;
bool palindrome(string & s){
for (char c: s){
++hash[c];
}
int count = 0;
for (auto a: hash){
if (a.second % 2 == 1){
count ++;
}
}
return count <= 1;
}
void dfs(string & s, vector<string> & result, string & current, char prev){
if (current.size() == (s.size() + 1) / 2){
result.push_back(current);
return;
}
for (int i = 0; i < 26; i++){
if (!current.empty() && 'a' + i == prev ) continue;
if (bag[i] != 0){
current += 'a' + i;
bag[i] --;
dfs(s, result, current, 'a' + i);
bag[i] ++;
current.pop_back();
}
}
return;
}
};