题目解析
小C需要对一个字符串进行特殊排序,字符串中包含字母、数字和问号。排序的规则如下:
- 问号:保持原始位置不变。
- 数字:保持原始位置不变,但需要按照从大到小的顺序进行排序。
- 字母:保持原始位置不变,但需要按照字典序从小到大的顺序进行排序。
思路
- 遍历字符串:首先遍历输入字符串,分别将数字和字母提取到两个不同的列表中。
- 排序:对数字列表进行降序排序,对字母列表进行升序排序。
- 重建字符串:再次遍历原始字符串,根据字符类型(数字、字母、问号)将排序后的字符放回原来的位置。
图解
- 假设输入字符串为 "1Ad?z?t24",处理过程如下:
- 提取数字:[1, 2, 4] → 排序后为 [4, 2, 1]
- 提取字母:[A, d, z] → 排序后为 [A, d, z]
- 重建字符串:
-
原始位置:1 → 4 -
原始位置:A → A -
原始位置:d → d -
原始位置:? → ? -
原始位置:z → z -
原始位置:? → ? -
原始位置:t → t -
原始位置:2 → 2 -
原始位置:4 → 1
代码详解
1.定义主类
public static String solution(String inp) {
2.初始化结果存储,创建存储列表
// 创建StringBuilder来存储结果
StringBuilder result = new StringBuilder(inp);
// 分别存储数字和字母
List<Character> numbers = new ArrayList<>();
List<Character> letters = new ArrayList<>();
3.遍历输入字符串
// 收集数字和字母
for (char c : inp.toCharArray()) {
if (Character.isDigit(c)) {
numbers.add(c);
} else if (Character.isLetter(c)) {
letters.add(c);
}
}
-
Character.isDigit(c):检查字符是否为数字,如果是,则将其添加到numbers列表中。
-
Character.isLetter(c):检查字符是否为字母,如果是,则将其添加到letters列表中。
4.排序数字、字母;初始化索引
// 对数字进行降序排序
Collections.sort(numbers, Collections.reverseOrder());
// 对字母进行升序排序
Collections.sort(letters);
// 分别记录数字和字母的索引
int numIndex = 0;
int letterIndex = 0;
5.重建字符串,返回
// 重新填充字符串
for (int i = 0; i < result.length(); i++) {
char c = inp.charAt(i);
if (Character.isDigit(c)) {
result.setCharAt(i, numbers.get(numIndex++));
} else if (Character.isLetter(c)) {
result.setCharAt(i, letters.get(letterIndex++));
}
// 问号保持原位置不变
}
return result.toString();
-
inp.charAt(i):获取原始字符串中索引i处的字符。
-
如果字符是数字,则用numbers列表中的下一个数字替换result中对应位置的字符,并增加numIndex。
-
如果字符是字母,则用letters列表中的下一个字母替换result中对应位置的字符,并增加letterIndex。
个人思考与分析
这个问题的关键在于如何有效地提取和排序字符,同时保持原始位置。使用StringBuilder可以方便地修改字符串,而使用ArrayList来存储数字和字母则使得排序变得简单。通过两次遍历字符串,我们可以高效地完成任务。在实际应用中,这种字符处理的需求非常常见,尤其是在数据清洗和格式化时。理解并掌握这种处理方式,可以帮助我们在未来的编程中更好地应对类似问题。