题目指路-->字符串字符类型排序问题 - MarsCode
问题描述
小C 需要对一个字符串进行特殊排序,这个字符串只包含三种字符类型:字母(大小写)、数字和问号。要求你按照以下规则进行排序:
- 问号的原始位置必须保持不变。
- 数字的原始位置必须保持不变,但数字要按照从大到小排序。
- 字母的原始位置必须保持不变,但字母要按照字典序从小到大排序。
你需要编写一个程序,帮助小C实现这个字符串的排序功能。
测试样例
样例1:
输入:
inp = "12A?zc"
输出:'21A?cz'
样例2:
输入:
inp = "1Ad?z?t24"
输出:'4Ad?t?z21'
样例3:
输入:
inp = "???123??zxy?"
输出:'???321??xyz?'
解决思路
- 分类:首先将字符串中的字符进行分类,分别提取数字、字母和问号。
- 我们需要遍历字符串中的每个字符,根据其类型将其分别存入数字列表、字母列表或问号列表。
-
排序:
- 数字:按从大到小排序。
- 字母:按字典序从小到大排序。
- 问号:无需排序,直接保留原位置。
- 也就是对数字列表进行降序排序,对字母列表进行升序排序。
- 重建字符串:将排序后的数字、字母按原来位置填入,问号保持原位置。
- 可以使用 StringBuilder 重新构建字符串,根据原始位置填充相应的数字或字母,问号保持原位。
完整代码
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static String solution(String inp) {
//使用 `List<Character>` 来存储数字和字母。遍历输入字符串,
//通过 `Character.isDigit(x)` 和 `Character.isLetter(x)` 判断每个字符的类型,
//然后分别添加到相应的列表中。
List<Character>shuzi=new ArrayList<Character>();
List<Character>zimu=new ArrayList<Character>();
//字符串转换成数组
char []arr=inp.toCharArray();
//使用增强型for循环提取数字或字母到列表中
for(char x:arr){
if(Character.isDigit(x)) shuzi.add(x);
else if(Character.isLetter(x)) zimu.add(x);
}
//数字降序排序
shuzi.sort(Collections.reverseOrder());
//字母升序排序
Collections.sort(zimu);
//使用 `StringBuilder` 来重建字符串
StringBuilder str=new StringBuilder();
//数字、字母的遍历位置
int shuziNo=0;
int zimuNo=0;
//遍历原字符串时,如果遇到数字,按排序后的顺序填入数字列表;
//如果遇到字母,按排序后的顺序填入字母列表;
//如果遇到问号,直接添加原问号。
for(char x:arr){
if(Character.isDigit(x)) {
str.append(shuzi.get(shuziNo));
shuziNo++;
}
else if(Character.isLetter(x)){
str.append(zimu.get(zimuNo));
zimuNo++;
}
//如果是问号,直接添加
else str.append(x);
}
//返回字符串形式
return str.toString();
}
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?"));
}
}
时间复杂度
字符串的遍历和字符分类的时间复杂度为 O(n),n 是字符串的长度。 对数字和字母分别进行排序,时间复杂度为 O(nlog^n),n 是字符的数量(最大为字符串长度)。
因此,总的时间复杂度为 O(nlog^n)。