120. 字符串字符类型排序问题
问题描述
小C 需要对一个字符串进行特殊排序,这个字符串只包含三种字符类型:字母(大小写)、数字和问号。要求你按照以下规则进行排序:
- 问号的原始位置必须保持不变。
- 数字的原始位置必须保持不变,但数字要按照从大到小排序。
- 字母的原始位置必须保持不变,但字母要按照字典序从小到大排序。
你需要编写一个程序,帮助小C实现这个字符串的排序功能。
题目链接:www.marscode.cn/practice/36…
思路解析
-
问号位置的保留:
- 由于问号的位置需要保持不变,我们可以直接在结果数组中保留问号的位置。
-
数字和字母的排序:
- 使用两个列表分别存储数字和字母,方便后续对它们进行排序。
-
将排序后的数字和字母放回原来的位置
- 再次遍历输入字符串,将排序后的数字和字母放回结果数组中对应的位置
解体步骤
-
初始化数据结构:
- 创建两个列表
digits
和letters
分别用于存储数字和字母。 - 创建一个字符数组
result
用于存储最终的结果。
- 创建两个列表
-
第一次遍历:
- 遍历输入字符串,将数字和字母分别存储到
digits
和letters
列表中,问号直接放入result
数组中。
- 遍历输入字符串,将数字和字母分别存储到
-
排序:
- 对
digits
列表进行从大到小排序。 - 对
letters
列表进行字典序排序。
- 对
-
第二次遍历:
- 再次遍历输入字符串,将排序后的数字和字母放回
result
数组中对应的位置。
- 再次遍历输入字符串,将排序后的数字和字母放回
复杂度分析
时间复杂度分析
-
第一次遍历输入字符串:
- 遍历输入字符串一次,时间复杂度为
O(n)
,其中n
是输入字符串的长度。
- 遍历输入字符串一次,时间复杂度为
-
对数字和字母进行排序:
- 假设数字的数量为
d
,字母的数量为l
,则排序的时间复杂度分别为O(d log d)
和O(l log l)
。 - 由于
d + l <= n
,所以排序的总时间复杂度为O(n log n)
。
- 假设数字的数量为
-
第二次遍历输入字符串:
- 再次遍历输入字符串一次,时间复杂度为
O(n)
。
- 再次遍历输入字符串一次,时间复杂度为
空间复杂度分析
-
存储数字和字母的列表:
- 使用两个列表
digits
和letters
,它们的空间复杂度分别为O(d)
和O(l)
,总的空间复杂度为O(n)
。
- 使用两个列表
-
结果数组:
- 使用一个字符数组
result
,空间复杂度为O(n)
。
- 使用一个字符数组
Code
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static String solution(String inp) {
// 用于存储数字和字母的位置和内容
List<Character> digits = new ArrayList<>();
List<Character> letters = new ArrayList<>();
char[] result = new char[inp.length()];
// 遍历输入字符串,将数字和字母分别存储,并保留问号的位置
for (int i = 0; i < inp.length(); i++) {
char c = inp.charAt(i);
if (Character.isDigit(c)) {
digits.add(c);
} else if (Character.isLetter(c)) {
letters.add(c);
} else {
result[i] = c; // 问号直接放入结果数组
}
}
// 对数字和字母进行排序
Collections.sort(digits, Collections.reverseOrder()); // 数字从大到小排序
Collections.sort(letters); // 字母按字典序排序
// 将排序后的数字和字母放回原位置
int digitIndex = 0;
int letterIndex = 0;
for (int i = 0; i < inp.length(); i++) {
if (result[i] == 0) { // 如果当前位置是空的(即不是问号)
if (Character.isDigit(inp.charAt(i))) {
result[i] = digits.get(digitIndex++);
} else {
result[i] = letters.get(letterIndex++);
}
}
}
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?"));
}
}
总结
学到的知识
-
字符串处理:
- 如何遍历字符串并根据字符类型进行分类。
- 如何对不同类型的字符进行排序。
-
排序算法:
- 使用
Collections.sort
对列表进行排序。 - 使用
Collections.reverseOrder
对列表进行逆序排序。
- 使用
-
复杂度分析:
- 理解并分析代码的时间复杂度和空间复杂度。
AI的使用感受
使用AI来解决编程问题可以带来以下几点感受:
-
快速获取思路:
- AI能够快速提供解题思路和算法步骤,帮助我们更好地理解问题。
-
代码实现辅助:
- AI可以提供代码框架和关键步骤的提示,帮助我们更快地编写代码。
-
学习效率提升:
- 通过AI的辅助,我们可以更快地掌握新的编程技巧和算法知识。
-
错误排查:
- AI可以帮助我们分析代码的复杂度,并提供优化建议,帮助我们更好地理解代码的性能。