问题描述
思路分析
我们需要对字符串中的字母、数字、问号按照规则进行排序,具体要求是:
- 问号的位置不变。
- 数字的位置不变,但数字之间要按照从大到小排序。
- 字母的位置不变,但字母之间要按照字典序排序。
解决此问题的思路分为以下几个步骤:
步骤 1:分离字符
遍历字符串,将字符分类存储:
- 字母存入一个列表中,用于后续的字母排序。
- 数字存入另一个列表中,用于后续的数字排序。
- 问号保留原位,不动。
通过这一过程,我们可以分离出所有需要排序的字母和数字。
步骤 2:对字母和数字分别排序
- 字母按字典序排序:直接调用 Java 的
Collections.sort()
方法对字母列表进行排序。 - 数字按从大到小排序:对数字列表使用
Collections.sort()
并传入Collections.reverseOrder()
,实现降序排列。
排序的结果分别保存在两个列表中。
步骤 3:重新组装字符串
- 再次遍历输入字符串,按照字符类型插入对应的值:
- 遇到字母时,从排序后的字母列表中取一个字母并插入到结果中。
- 遇到数字时,从排序后的数字列表中取一个数字并插入到结果中。
- 遇到问号时,直接在结果中保留问号。
通过这种方式,能够保持问号位置不变,同时按照要求对字母和数字进行了重新排序。
参考代码(Java)
import java.util.ArrayList;
import java.util.Collections;public class Main {public static String solution(String inp) {// 创建列表存储字母和数字ArrayList<Character> letters = new ArrayList<>();ArrayList<Character> digits = new ArrayList<>();// 遍历字符串,将字母和数字分离for (char ch : inp.toCharArray()) {if (Character.isLetter(ch)) {letters.add(ch);} else if (Character.isDigit(ch)) {digits.add(ch);}}// 对字母按字典序排序Collections.sort(letters);// 对数字按从大到小排序digits.sort(Collections.reverseOrder());// 用于重新组装字符串的StringBuilderStringBuilder result = new StringBuilder();// 分别维护字母和数字的索引int letterIndex = 0;int digitIndex = 0;// 遍历输入字符串,根据需要插入排序后的字母和数字for (char ch : inp.toCharArray()) {if (Character.isLetter(ch)) {result.append(letters.get(letterIndex++));} else if (Character.isDigit(ch)) {result.append(digits.get(digitIndex++));} else { // 问号保留原位result.append(ch);}}return result.toString();}public static void main(String[] args) {// 测试用例System.out.println(solution("12A?zc").equals("21A?cz"));System.out.println(solution("1Ad?z?t24").equals("4Ad?t?z21"));System.out.println(solution("???123??zxy?").equals("???321??xyz?"));}
}
代码分析
1. 方法声明和初始化
public static String solution(String inp) {// 创建列表存储字母和数字ArrayList<Character> letters = new ArrayList<>();ArrayList<Character> digits = new ArrayList<>();
- 定义
solution
方法,用于实现字符串排序逻辑。 - 初始化两个列表:
letters
用于存储所有字母。digits
用于存储所有数字。
2. 遍历字符串,分类字符
for (char ch : inp.toCharArray()) {if (Character.isLetter(ch)) {letters.add(ch);} else if (Character.isDigit(ch)) {digits.add(ch);}
}
- 遍历输入字符串
inp
,使用toCharArray()
转换成字符数组。 - 对每个字符
ch
:- 如果是字母 (
Character.isLetter(ch)
),存入letters
。 - 如果是数字 (
Character.isDigit(ch)
),存入digits
。 - 问号等特殊字符直接跳过,不加入任何列表。
- 如果是字母 (
此步骤完成后:
- 字母和数字被分离,分别存储在
letters
和digits
中。 - 问号的位置没有被改变。
3. 对字母和数字排序
// 对字母按字典序排序
Collections.sort(letters);
// 对数字按从大到小排序
digits.sort(Collections.reverseOrder());
- 调用
Collections.sort()
对letters
按字典序排序(从小到大)。 - 使用
Collections.sort()
对digits
按降序排列(通过Collections.reverseOrder()
实现)。
排序后的结果:
letters
按字母表顺序排列。digits
从大到小排列。
4. 重新组装字符串
StringBuilder result = new StringBuilder();
int letterIndex = 0;
int digitIndex = 0;for (char ch : inp.toCharArray()) {if (Character.isLetter(ch)) {result.append(letters.get(letterIndex++));} else if (Character.isDigit(ch)) {result.append(digits.get(digitIndex++));} else { // 问号保留原位result.append(ch);}
}
- 初始化
StringBuilder
用于存储最终的结果字符串。 - 使用两个索引
letterIndex
和digitIndex
,分别跟踪letters
和digits
列表中已插入的元素位置。
遍历输入字符串 inp
的每个字符:
- 如果是字母,从
letters
中取出排序后的下一个字母,加入结果中。 - 如果是数字,从
digits
中取出排序后的下一个数字,加入结果中。 - 如果是问号,直接将问号添加到结果中,位置保持不变。
5. 返回结果字符串
return result.toString();
- 将
StringBuilder
转换为字符串并返回。