267. Palindrome Permutation II

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完全不用受到限制。

易错点

  1. 进入dfs前数量减半(奇数此时也被取偶)
  2. 所有需要修改的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个字母吧。面试的时候不问清楚秒挂。放在这引以为戒,里面也包含一些坑:

  1. 如果想对hash进行修改,在遍历的时候就要用&
  2. 长度判断,先+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;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值