767. 重构字符串
给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
拆解字符串+重构字符串
先用一个26位vector存储每一个字母出现次数,出现次数大于字符串长度一半时无法重构,其他情况都可以重构。
按出现次数由大到小排序vector,保证先插入出现次数多的元素。
重构时按奇数偶数位置插入元素。
class Solution {
public:
string reorganizeString(string S) {
int len = S.size();
vector<pair<int, int> > arr(26);
for (const char& c : S)
++arr[c - 'a'].second;
int index = 0;
for (auto& p : arr)
{
p.first = index++;
if (p.second > ((len + 1) >> 1))
return "";
}
sort(arr.begin(), arr.end(), [](const pair<int, int>& a, const pair<int, int>& b){
return a.second > b.second;
});
string res = S;
index = 0;
// 置放奇数位
for (int i = 0; i < len; i += 2)
{
if (arr[index].second == 0)
++index;
res[i] = ('a' + arr[index].first);
--arr[index].second;
}
// 置放偶数位
for (int i = 1; i < len; i+= 2)
{
if (arr[index].second == 0)
++index;
res[i] = ('a' + arr[index].first);
--arr[index].second;
}
return res;
}
};
查找碰撞元素,查找可插入位置插入
先从index前面找,再从index后面找
class Solution {
public:
string reorganizeString(string S)
{
int len = S.length();
if (len <= 1) {
return S;
}
for (int i = 1; S[i] != 0;) {
if (S[i] != S[i - 1]) {
i++;
continue;
}
// 在前面找位置置换
if (ReplaceCharOfStringFront(S, i - 1)) {
continue;
}
// 在后面找位置置换
if (ReplaceCharOfStringBack(S, i)) {
continue;
}
// 找不到位置置换,就返回空
return "";
}
return S;
}
// 在前面找,找到,就删除当前位置,插入当前字符
bool ReplaceCharOfStringFront(string& s, int idx)
{
for (int i = 0; i <= (idx - 1); i++) {
if (s[i] != s[idx] && (i == 0 || s[i - 1] != s[idx])) {
char ch = s[idx];
s.erase(idx, 1);
s.insert(i, 1, ch);
return true;
}
}
return false;
}
// 在后面找,找到,就删除当前位置,插入当前字符
bool ReplaceCharOfStringBack(string& s, int idx)
{
int len = s.length();
for (int i = idx + 1; i < len; i++) {
if (s[i] != s[idx] && (s[i + 1] != s[idx])) {
char ch = s[idx];
s.erase(idx, 1);
s.insert(i, 1, ch);
return true;
}
}
// 找不到
return false;
}
};