题目描述:
小C 需要对一个字符串进行特殊排序,这个字符串只包含三种字符类型:字母(大小写)、数字和问号。要求你按照以下规则进行排序:
- 问号的原始位置必须保持不变。
- 数字的原始位置必须保持不变,但数字要按照从大到小排序。
- 字母的原始位置必须保持不变,但字母要按照字典序从小到大排序。
你需要编写一个程序,帮助小C实现这个字符串的排序功能。
思路:
1. 整体思路
整体思路是先将输入字符串中的字母、数字和其他字符(这里主要是问号)分别提取出来,然后对字母和数字分别按照要求进行排序,最后再按照原始字符串中字符的类型将排好序的字母和数字重新组合到相应位置,生成排序后的字符串。
2. 具体步骤
分离字符类型(步骤 1)
- 首先创建了两个
ArrayList,分别用于存储字符串中的字母letters和数字digits。同时创建了一个字符数组result,其长度与输入字符串inp相同,用于后续存储排序后的结果,初始时里面的元素默认值为\u0000(对应 ASCII 码值为 0 的字符,这里可简单理解为空字符)。 - 然后遍历输入字符串
inp中的每个字符。对于每个字符c,通过Character.isLetter(c)判断是否为字母,如果是则添加到letters列表中;通过Character.isDigit(c)判断是否为数字,如果是则添加到digits列表中;如果既不是字母也不是数字(这里实际就是问号等其他字符),则直接将该字符按原始位置存储到result数组中。
排序(步骤 2)
- 对于提取出来的字母列表
letters,使用Collections.sort(letters)方法按照字典序从小到大对字母进行排序。这是利用了Collections.sort方法对实现了Comparable接口的对象列表(这里的Character类实现了该接口)的默认排序行为,即按照字典序排序。 - 对于提取出来的数字列表
digits,使用digits.sort(Collections.reverseOrder())进行排序。这里通过Collections.reverseOrder()获取一个比较器,它可以让数字按照从大到小的顺序进行排序。
重组字符串(步骤 3)
- 定义了两个索引变量
letterIndex和digitIndex,分别用于跟踪已经处理到的字母和数字在各自排好序的列表中的位置。 - 再次遍历输入字符串
inp的每个位置。当result[i] == 0时,表示该位置是原始字符串中字母或数字的位置(因为问号等其他字符已经在第一步按原始位置存储到result数组中了)。然后通过判断原始字符串该位置的字符是字母还是数字,从排好序的相应列表(letters或digits)中取出对应字符,并存储到result数组的该位置。 - 最后,将
result数组转换为String类型并返回,得到按照要求排序后的字符串。
代码实现:
import java.util.*;
public class Main {
public static String solution(String inp) {
// 1. 分离字符类型
List<Character> letters = new ArrayList<>();
List<Character> digits = new ArrayList<>();
char[] result = new char[inp.length()];
for (int i = 0; i < inp.length(); i++) {
char c = inp.charAt(i);
if (Character.isLetter(c)) {
letters.add(c);
} else if (Character.isDigit(c)) {
digits.add(c);
} else {
result[i] = c; // 问号保持原位
}
}
// 2. 排序
Collections.sort(letters); // 字母按字典序从小到大排序
digits.sort(Collections.reverseOrder()); // 数字按从大到小排序
// 3. 重组字符串
int letterIndex = 0;
int digitIndex = 0;
for (int i = 0; i < inp.length(); i++) {
if (result[i] == 0) { // 非问号位置
if (Character.isLetter(inp.charAt(i))) {
result[i] = letters.get(letterIndex++);
} else if (Character.isDigit(inp.charAt(i))) {
result[i] = digits.get(digitIndex++);
}
}
}
return new String(result);
}
public static void main(String[] args) {
// Add your test cases here
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?"));
}
}