版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/89913987
给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab"
输出: "aba"
示例 2:
输入: S = "aaab"
输出: ""
注意:
S 只包含小写字母并且长度在[1, 500]区间内。
这道题我们采用贪心策略的思想,每次将当前剩余次数最多
和剩余次数次多
的字符取出来放到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;
}
};