一、题目
给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = “aab”
输出: “aba”
示例 2:
输入: S = “aaab”
输出: “”
注意:
S 只包含小写字母并且长度在[1, 500]区间内。
二、解题
思路:
- “两相邻的字符不同” 推出重复次数最多的字符不能超过n/2 + 1 个,否则不能构成符合条件的字符串
- 生成哈希表,记录每个字符出现的个数,将最大字符(X)从哈希表剔除
- 如果满足条件,遍历哈希表,将X放在遍历开头加入,直到除X外的所有字符都追加完成
- 此时若还有X没有追加到重构的字符串里,从重构的字符串尾部判断是否能追加插入X
另外,题目说了是纯字母的,可以通过转成int数组来解决。性能上应该能提升不少。习惯用通用解法,这里编码的时候就么有写。
按这个思路,其实自己觉得应该能挺快的。结果虽然不会超时,但是还是算不上一个好的解法:
代码如下:
class Solution {
public String reorganizeString(String S) {
// 将输入拆分为字符数组
String[] cArr = S.split("");
// 确定阈值
int origLength = S.length();
int max = origLength / 2 ;
if(origLength % 2 == 1) {
max = max + 1;
}
// 遍历确定各元素个数
Map<String, Integer> hash = new HashMap<>();
int maxLength = 0;
// 用于记录最大的key
String maxKey = cArr[0];
for(int i = 0; i < cArr.length; ++i) {
int currentSize = hash.getOrDefault(cArr[i], 0) + 1;
if(maxLength < currentSize) {
maxLength = currentSize;
maxKey = cArr[i];
}
hash.put(cArr[i], currentSize);
}
// 校验是否满足要求
if(maxLength > max) {
return "";
}
// 如果没有溢出, 则生成符合要求的字符串
// 将最大的key作为开始,遍历所有元素生成满足要求的字符串
String maxKeyStr = maxKey;
char maxKeyChar = maxKey.charAt(0);
hash.remove(maxKeyStr);
String ret = "";
while(origLength-- > 0 && maxLength-- > 0) {
ret = ret+maxKey;
for(Map.Entry<String, Integer> entry : hash.entrySet()) {
if(entry.getValue() > 0) {
ret = ret + entry.getKey();
entry.setValue(entry.getValue() - 1);
origLength--;
}
}
// 如果hash里的字母都写完了,退出
if(origLength == maxLength) {
break;
}
}
// 遍历完尚未清空最大数组,将剩余的maxKey插入结果中
StringBuilder sbRet=new StringBuilder(ret);
if(maxLength > 0) {
int i = 0;
while(maxLength-- > 0) {
// 如果插入位置左右都没有maxKey,则后续都可以直接插入
while((i == 0 && sbRet.charAt(ret.length() - 1 - i) == maxKeyChar)
|| (i > 0 && (sbRet.charAt(ret.length() - 1 - i) == maxKeyChar || sbRet.charAt(ret.length() - 1 - i + 1) == maxKeyChar))) {
i++;
}
sbRet.insert(ret.length() - i++, maxKey);
}
}
return sbRet.toString();
}
}
三、题解
有些题解说先把X放在下标偶数位置,再随意安插其他字符就可以得出解了,但是如果是aaaabbbbc
这种,a_a_a_a_
这样安插完后,再随意安插的话就有abacababb
,会出现重复的情况,这个还没有get到题解的意思。
另外官方题解:重构字符串看着可以说是比较权威了,值得研读,先休息,明天学习下题解。