题目描述
给你一个混合了数字和字母的字符串 s,其中的字母均为小写英文字母。
请你将该字符串重新格式化,使得任意两个相邻字符的类型都不同。也就是说,字母后面应该跟着数字,而数字后面应该跟着字母。
请你返回 重新格式化后 的字符串;如果无法按要求重新格式化,则返回一个 空字符串 。
示例 1:
输入:s = "a0b1c2"
输出:"0a1b2c"
解释:"0a1b2c" 中任意两个相邻字符的类型都不同。 "a0b1c2", "0a1b2c", "0c2a1b" 也是满足题目要求的答案。
解题思路
这道题实际就是字段串处理的题目,基本思路如下:
- 对字符串内的字符进行分类,分成数字和字符,分别放到2个List中;
- 比较2个List的长度,如果2个List的长度相差大于等于2,那么直接返回空字符串;
- 如果2个List的长度相差小于2,则对结果进行merge;
代码实现
import java.util.ArrayList;
import java.util.List;
class Solution2 {
public String reformat(String s) {
List<Character> l1 = new ArrayList<>(s.length());
List<Character> l2 = new ArrayList<>(s.length());
for (char c : s.toCharArray()) {
if (Character.isDigit(c)) {
l1.add(c);
} else {
l2.add(c);
}
}
if (l1.size() > l2.size()) {
return merge(l1, l2);
} else {
return merge(l2, l1);
}
}
private String merge(List<Character> l1, List<Character> l2) {
if (l1.size() - l2.size() >= 2) {
return "";
}
char[] chars = new char[l1.size() + l2.size()];
int i1 = 0;
int i2 = 0;
int i = 0;
while (i1 < l1.size() && i2 < l2.size()) {
chars[i++] = l1.get(i1++);
chars[i++] = l2.get(i2++);
}
if (i1 < l1.size()) {
chars[i++] = l1.get(i1++);
}
return new String(chars);
}
}
代码优化
上述代码在耗时方面不是最优的,为了能优化耗时,进行如下改造:
- 提供一个变量c1统计字符串出现的次数;
- 用数组的长度减去c1,获得非数字的长度,记录为c2;
- 如果c2 - c1 的绝对值大于等于2,直接返回空字符串;
- 如果c2 - c1 的绝对值小于2,则对字符数组进行merge;
字符数组merge逻辑如下:
- 如果数字字符更多,则数字字符从0开始计算,非数字字符从1开始计算;否则数字字符从1开始计算,非数字字符从0开始计算
- 接着遍历数组,设置每个字符对应的下标值;
- 最后返回结果。
按照上述思路代码实现如下:
class Solution {
public String reformat(String s) {
int c1 = 0;
char[] array = s.toCharArray();
for (char c : array) {
if (isDigit(c)) {
c1++;
}
}
int c2 = array.length - c1;
return merge(c1, c2, array);
}
boolean isDigit(char c) {
return c >= '0' && c <= '9';
}
private String merge(int c1, int c2, char[] array) {
if (c1 - c2 >= 2 || c1 - c2 <= -2) {
return "";
}
if (c1 > c2) {
c1 = 0;
c2 = 1;
} else {
c1 = 1;
c2 = 0;
}
char[] res = new char[array.length];
for (char c : array) {
if (isDigit(c)) {
res[c1] = c;
c1 += 2;
} else {
res[c2] = c;
c2 += 2;
}
}
return new String(res);
}
}
总结
这道题整体就是字符串的解析和判定,为了提升执行效率,我把临时存储2种类型的List给取消了,在字符合并时也做了优化,最终达到最优的耗时。当然,如果有更加好、更加高效的思路,欢迎回复。