字符串字符类型排序问题刷题笔记
一、题目解析
问题描述
给定一个只包含字母(大小写)、数字和问号的字符串,按照以下规则对字符串排序:
- 问号的位置保持不变。
- 数字的位置保持不变,但数字按从大到小排序。
- 字母的位置保持不变,但字母按字典序从小到大排序。
要求:保留问号原始位置不动,分别对数字和字母排序后插入到对应的位置。
二、解题思路
-
分类提取
- 遍历字符串,提取所有的数字和字母,分别存储在两个容器中。
- 问号不需要存储,保持原样。
-
分类排序
- 对提取的数字按降序排序。
- 对提取的字母按字典序升序排序。
-
重构字符串
- 遍历原字符串,根据字符类型逐步插入排好序的数字、字母或问号。
-
时间复杂度分析
- 字符提取和重新构建字符串的复杂度为 O(n)。
- 数字和字母排序的复杂度为 O(klogk),其中 k 是数字或字母的数量。
- 整体复杂度为 O(n+klogk),在输入规模允许的情况下足够高效。
三、代码实现
以下是代码以及注释:
import java.util.Arrays;
public class Main {
public static String solution(String inp) {
// 分别存储数字和字母,用于排序
StringBuilder digits = new StringBuilder();
StringBuilder letters = new StringBuilder();
// 遍历字符串,提取数字和字母
for (char c : inp.toCharArray()) {
if (Character.isDigit(c)) {
digits.append(c); // 收集数字
} else if (Character.isLetter(c)) {
letters.append(c); // 收集字母
}
}
// 对数字按从大到小排序
char[] digitArray = digits.toString().toCharArray();
Arrays.sort(digitArray); // 升序排序
digits = new StringBuilder(new String(digitArray)).reverse(); // 逆序
// 对字母按字典序排序
char[] letterArray = letters.toString().toCharArray();
Arrays.sort(letterArray); // 升序排序
letters = new StringBuilder(new String(letterArray));
// 构建最终结果
StringBuilder result = new StringBuilder();
int digitIndex = 0, letterIndex = 0;
for (char c : inp.toCharArray()) {
if (Character.isDigit(c)) {
// 插入排好序的数字
result.append(digits.charAt(digitIndex++));
} else if (Character.isLetter(c)) {
// 插入排好序的字母
result.append(letters.charAt(letterIndex++));
} else {
// 保留问号
result.append(c);
}
}
return result.toString();
}
public static void main(String[] args) {
// 测试样例
System.out.println(solution("12A?zc").equals("21A?cz")); // 测试 1
System.out.println(solution("1Ad?z?t24").equals("4Ad?t?z21")); // 测试 2
System.out.println(solution("???123??zxy?").equals("???321??xyz?")); // 测试 3
}
}
四、知识总结
-
字符串分类提取
- 使用
Character.isDigit和Character.isLetter判断字符类型,分别提取数字和字母。 - 对于特殊字符(如问号),无需处理直接保留。
- 使用
-
排序技巧
- 利用
Arrays.sort对字符数组进行排序,处理数字和字母分别排序的问题。 - 数字排序后通过
StringBuilder.reverse()转为降序,字母排序后直接按升序插入。
- 利用
-
结果重构
- 通过原字符串的位置关系,按字符类型分别插入排序后的数字、字母,确保问号位置不变。
五、学习建议
-
分类提取与排序
- 在处理字符串分类问题时,优先分离不同类型的数据,分步操作更清晰。
- 排序操作需要结合具体需求选择升序或降序。
-
逐步构建结果
- 使用
StringBuilder构建结果字符串,比直接拼接效率更高。 - 遍历原字符串时,逐步插入分类排序后的数据,确保位置关系一致。
- 使用
-
测试覆盖性
-
测试样例需覆盖以下情况:
- 包含大量问号的字符串。
- 字符类型混合的复杂字符串。
- 全数字或全字母的字符串。
-
六、个人总结
本题考察了字符串分类、排序以及位置保持的综合处理能力。通过逐步分类提取、排序和构建结果,可以高效解决这一问题。对于复杂字符串操作,分离任务并按类型处理是实现正确性和高效性的关键。