题链:https://leetcode-cn.com/problems/reorganize-string/
我的思路:我考虑的是插空法。首先,按插空法,假设一个字母出现的次数为k,那么我们需要k-1个其他字母将他们分开,所以如果一个字母出现次数n-k>k-1,否则就无法重构。贪心策略就是每次弹出出现次数最多的字母a(假设有k个)。首先用掉一个,剩下k-1个,每一个之前都放一个当前优先队列中出现次数最多的字符b,如果b还有再将它放入队列。
struct node{
int pos,num;
friend bool operator < (node a,node b){
if(a.num==b.num) return a.pos>b.pos;
return a.num<b.num;
}
};
class Solution {
public:
string reorganizeString(string s) {
int n = s.size();
if(n==0) return "";
int num[26]={0};
priority_queue<node> q;
for(int i=0;i<n;i++)
num[s[i]-'a']++;
for(int i=0;i<26;i++){
if(n-num[i]<num[i]-1)
return "";
if(num[i]>0)
q.push(node{i,num[i]});
}
string ans="";
while(!q.empty()){
node now = q.top();
q.pop();
ans+=('a'+now.pos);
--now.num;
while(now.num>0){
if(q.empty()) return "";
node temp=q.top();
q.pop();
ans+=('a'+temp.pos);
--temp.num;
if(temp.num>0) q.push(temp);
ans+=('a'+now.pos);
--now.num;
}
}
return ans;
}
};
官方题解1:感觉不能重构的证明没有插空法好理解。也是优先队列,每次弹出两个堆顶,如果减1后还有就再放入队列。
struct node{
int pos,num;
friend bool operator < (node a,node b){
if(a.num==b.num) return a.pos>b.pos;
return a.num<b.num;
}
}now1,now2;
class Solution {
public:
string reorganizeString(string s) {
int n = s.size();
if(n==0) return "";
int num[26]={0};
priority_queue<node> q;
for(int i=0;i<n;i++)
num[s[i]-'a']++;
for(int i=0;i<26;i++){
if(n-num[i]<num[i]-1)
return "";
if(num[i]>0)
q.push(node{i,num[i]});
}
string ans="";
while(!q.empty()){
now1=q.top();
q.pop();
ans += ('a'+now1.pos);
--now1.num;
if(!q.empty()){
now2=q.top();
q.pop();
ans += ('a'+now2.pos);
--now2.num;
if(now2.num) q.push(now2);
}
if(now1.num) q.push(now1);
}
return ans;
}
};
官方题解2:先放奇数位,再放偶数位。
struct node{
int pos,num;
};
bool cmp (node a,node b){
if(a.num==b.num) return a.pos<b.pos;
return a.num>b.num;
}
class Solution {
public:
string reorganizeString(string s) {
int n = s.size();
if(n==0) return "";
int num[26]={0};
node a[26];
string ans="";
for(int i=0;i<n;i++)
num[s[i]-'a']++,ans+='a';
for(int i=0;i<26;i++){
if(n-num[i]<num[i]-1) return "";
a[i]=node{i,num[i]};
}
sort(a,a+26,cmp);
int in1=0,in2=1;
for(int i=0;i<26;i++){
while(a[i].num){
if(in1>=n)
ans[in2]=('a'+a[i].pos),in2+=2;
else
ans[in1]=('a'+a[i].pos),in1+=2;
--a[i].num;
}
}
return ans;
}
};