LeetCode 重构字符串(优先队列+贪心策略)

给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。

若可行,输出任意可行的结果。若不可行,返回空字符串。

示例 1:

输入: S = "aab"
输出: "aba"

示例 2:

输入: S = "aaab"
输出: ""

注意:

S 只包含小写字母并且长度在[1, 500]区间内。

思 路 分 析 : \color{blue}{思路分析:} 这道题我们采用贪心策略的思想,每次将当前剩余次数最多剩余次数次多的字符取出来放到resStr的尾部,最后如果只剩下一个字符并且这个字符的剩余的次数超过了1,则说明这个字符串无法重构,否则resStr即是重构结果。

class Solution {
public:
    //自定义排序结构体
    struct cmp{
        bool operator()(const pair<char, int>& p1,const pair<char, int>& p2){
            return p1.second < p2.second;
        }
    };
    string reorganizeString(string S) {
        //第一步:统计各个字符出现的次数
        vector<int> lettersCount(26, 0);
        for (auto ch : S){
            lettersCount[ch - 'a'] += 1;
        }
        //第二步:构造自定义排序的优先队列(按照出现的次数从高到低进行排序)
        priority_queue<pair<char, int>, vector<pair<char, int>>, cmp> myPrioQue;
        for (int i = 0; i < 26; ++i){
            if (lettersCount[i] != 0){
                myPrioQue.push({char(i + 'a'), lettersCount[i]});
            }
        }
        //第三步:每次将当前`剩余次数最多`和`剩余次数次多`的字符取出来放到resStr的尾部
        string res = "";
        while (myPrioQue.size() >= 2) {
            pair<char, int> p1 = myPrioQue.top();
            myPrioQue.pop();
            pair<char, int> p2 = myPrioQue.top();
            myPrioQue.pop();
            res.push_back(p1.first);
            res.push_back(p2.first);
            p1.second--;
            p2.second--;
            //剩余次数自减后,如果还剩余次数,则需要放回优先队列
            if(p1.second!=0){
                myPrioQue.push(p1);
            }
            if(p2.second!=0){
                myPrioQue.push(p2);
            }
        }
        if(myPrioQue.top().second >= 2){
            //只剩下一个字符并且这个字符的剩余的次数超过了1,则说明这个字符串无法重构
            return "";
        }
        else if(myPrioQue.size() > 0){
            res.push_back(myPrioQue.top().first);
        }
        return res;
    }
};

LeetCode 重构字符串(优先队列+贪心策略)_第1张图片

你可能感兴趣的:(LeetCode,字符串,贪心算法,优先队列)