题目描述:
给定一个字符串S
,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab" 输出: "aba"
示例 2:
输入: S = "aaab" 输出: ""
刚看到这个题,就觉得直接用一个数组记录下S每个字符出现的次数,不可以重构的原因无非就是一个字符出现的次数大于一个阈值,若S的长度为偶数时,阈值为长度的一半,若S的长度为奇数时,则阈值为长度加1的一半,超过这个阈值则不能重构。能重构的情况下,找到出现次数最大的,每次先把他加到结果result中,在加其他的。直到result的长度等于S的长度。结果超时了,代码如下:
class Solution {
public:
string reorganizeString(string S) {
//将S中每个字符存到数组中
int n = S.size();
vector<int>temp(26,0);
int maxx = 0;
int index = 0;
for (int i = 0; i < n; i++)
{
temp[S[i] - 'a']++;
maxx = max(maxx, temp[S[i] - 'a']);
if (temp[S[i] - 'a'] > maxx)
{
maxx = temp[S[i] - 'a'];
index = i;
}
}
if (maxx > (n / 2)&&(n%2==0))
{
return "";
}
string result = "";
while (result.size() <n)
{
for (int i = 0; i < 26; i++)
{
if (temp[i] != 0&&i!=index)
{
result += index + 'a';
result += i + 'a';
temp[index]--;
temp[i]--;
}
}
}
return result;
}
};
然后又想到是每次都要选出出现次数最大的,其实就是相当于最大堆,然后经过改进,用代码堆来实现,其中用到了c++11中lambda表达式来进行判断。代码如下:
class Solution {
public:
string reorganizeString(string S) {
//将S中每个字符存到数组中
int n = S.size();
vector<int>temp(26,0);
int maxx = 0;
int index = 0;
for (int i = 0; i < n; i++)
{
temp[S[i] - 'a']++;
maxx = max(maxx, temp[S[i] - 'a']);
if (temp[S[i] - 'a'] > maxx)
{
maxx = temp[S[i] - 'a'];
index = i;
}
}
if (maxx > ((n+1) / 2)&&(n%2==0))
{
return "";
}else if (maxx > (n + 1) / 2 && (n % 2 == 1))
{
return "";
}
auto cmp = [&](const char& letter1, const char& letter2) {
return temp[letter1 - 'a'] < temp[letter2 - 'a'];
};
priority_queue<char, vector<char>, decltype(cmp)>queue{ cmp };
for (char c = 'a'; c <= 'z'; c++) {
if (temp[c - 'a'] > 0) {
queue.push(c);
}
}
string result = "";
while (queue.size() >1)
{
char letter1 = queue.top(); queue.pop();
char letter2 = queue.top(); queue.pop();
result += letter1;
result += letter2;
int index1 = letter1 - 'a', index2 = letter2 - 'a';
temp[index1]--;
temp[index2]--;
if (temp[index1] > 0)
{
queue.push(letter1);
}
if (temp[index2] > 0)
{
queue.push(letter2);
}
}
if (queue.size() > 0)
{
result += queue.top();
}
return result;
}
};