给定一个字符串 s ,检查是否能重新排布其中的字母,使得两相邻的字符不同。
返回 s 的任意可能的重新排列。若不可行,返回空字符串 “” 。
示例 1:
输入: s = “aab”
输出: “aba”
示例 2:
输入: s = “aaab”
输出: “”
提示:
1 <= s.length <= 500
s 只包含小写字母
优先队列
class Solution {
public:
string reorganizeString(string s) {
if(s.size() < 2){
return s;
}
int n = s.size();
vector<int> counts(26, 0);
int maxCount = 0;
for(int i = 0; i < n; i++){
counts[s[i] - 'a']++;
maxCount = max(maxCount, counts[s[i] - 'a']);
}
if(maxCount > (n + 1) / 2){
return "";
}
auto cmp = [&](const char& letter1, const char& letter2){
return counts[letter1 - 'a'] < counts[letter2 - 'a'];
};
priority_queue<char, vector<char>, decltype(cmp)> q(cmp);
for(char c = 'a'; c <= 'z'; c++){
if(counts[c - 'a'] > 0){
q.push(c);
}
}
string new_s = "";
while(q.size() > 1){
char letter1 = q.top();
q.pop();
char letter2 = q.top();
q.pop();
new_s += letter1;
new_s += letter2;
counts[letter1 - 'a']--;
counts[letter2 - 'a']--;
if(counts[letter1 - 'a'] > 0){
q.push(letter1);
}
if(counts[letter2 - 'a'] > 0){
q.push(letter2);
}
}
if(q.size() > 0){
new_s += q.top();
}
return new_s;
}
};
时间复杂度:O(nlog∣Σ∣+∣Σ∣)
空间复杂度:O(∣Σ∣)
这道题是基于贪心的思路,使用优先队列来完成。首先当s的长度小于2的时候,一定有重构字符串。接着当s中某个字符的个数大于字符串s长度的一半的时候(s长度如果是奇数则向上取整),那么则无法有重构字符串。接着我们使用贪心的思路,我们每次取出字符数量最多的两个字符,将他们加入到重构字符串new_s中。我们要比较字符数量最多的数量,可以用最大堆来做,cmp是我们自己写的比较函数。每次将最多数量的字符加入到new_s后,将他们数量都减去1,当他们数量还大于0的时候,才将它们继续加入到q中。
当q中只剩下一种字符,就加入new_s中。最后返回new_s。
这道题还可以用计数的贪心方法实现O(n)的算法,这里不涉及