给你一个混合了数字和字母的字符串 s,其中的字母均为小写英文字母。
请你将该字符串重新格式化,使得任意两个相邻字符的类型都不同。也就是说,字母后面应该跟着数字,而数字后面应该跟着字母。
请你返回 重新格式化后 的字符串;如果无法按要求重新格式化,则返回一个 空字符串 。
示例 1:
输入:s = "a0b1c2"
输出:"0a1b2c"
解释:"0a1b2c" 中任意两个相邻字符的类型都不同。 "a0b1c2", "0a1b2c", "0c2a1b" 也是满足题目要求的答案。
这道题实际就是字段串处理的题目,基本思路如下:
-
- import java.util.ArrayList;
- import java.util.List;
-
- class Solution2 {
- public String reformat(String s) {
- List
l1 = new ArrayList<>(s.length()); - List
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
l1, List 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);
- }
-
- }
上述代码在耗时方面不是最优的,为了能优化耗时,进行如下改造:
字符数组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给取消了,在字符合并时也做了优化,最终达到最优的耗时。当然,如果有更加好、更加高效的思路,欢迎回复。