一.问题描述
小R有一个字符串 word,该字符串由数字和小写英文字母组成。小R想用空格替换每一个不是数字的字符。然后,他希望统计在替换后剩下的整数中,不同整数的数目。
例如,给定字符串 "a123bc34d8ef34",替换后形成的字符串是 " 123 34 8 34",剩下的整数是 "123"、"34"、"8" 和 "34"。不同的整数有三个,即 "123"、"34" 和 "8"。
注意,只有当两个整数的不含前导零的十进制表示不同,才认为它们是不同的整数。
二.思路分析
这个问题其实就是将字母之间的数字看成不同的整体,然后在去除每个数字前的前导零,最后将所有数字进行比较,算不重复的数字有多少。对此我们可以按照以下步骤进行:
1..数据结构的选择
StringBuilder:用于构建替换后的字符串
Set:用于存储不同的整数,自动去重。
2.替换非数字字符:
遍历字符串 word 中的每个字符。
如果字符是数字(即在 '0' 到 '9' 之间),则保留;如果字符不是数字,则替换为空格。
3. 分割字符串:
将替换后的字符串按照空格分割,得到一个字符串数组,每个元素都是一个可能的整数。
4.去除前导零:
对于每一个候选整数,去除其前导零。例如,"00123" 变为 "123","08" 变为 "8"。
注意 "0" 本身是一个有效的整数,不需要去除。
5.统计不同整数:
使用一个集合(Set)来存储所有不同的整数,因为集合自动去重。
遍历所有候选整数,将去前导零后的整数添加到集合中。
6.输出结果:
最后,集合的大小即为不同整数的数目。
三.代码实现
在写代码时我遇到了前导零如何去除的问题,因为我用C语言的思想去写Java时,我的代码出现了报错,于是我就求助了豆包自带的AI,最后成功的写出来了。
public static int solution(String word) {
// write code here
StringBuilder s = new StringBuilder();
for (int i = 0; i < word.length(); i++) {
if(Character.isDigit(word.charAt(i))){
s.append(word.charAt(i));
}else{
s.append(' ');
}
}
String[] w = s.toString().split("\\s+");
Set<String> uniqueNumbers = new HashSet<>(); for (String num : w) {
if (!num.isEmpty()) {
// 去除前导零
String trimmedNum = num.replaceFirst("^0+(?!$)", "");
uniqueNumbers.add(trimmedNum);
}
}
return uniqueNumbers.size();
}
四.时间复杂度
O(n):该算法的时间复杂度主要取决于for循环的循环条件,因此为O(n),n是输入字符串word的长度。
1. 字符串长度(n) :
输入字符串 word 的长度是决定时间复杂度的主要因素。
2 字符检查:
Character.isDigit() 方法用于检查每个字符是否为数字,这是一个常数时间操作 O(1)。
3.字符串拼接:
使用 StringBuilder 的 append() 方法来构建新的字符串,这也是一个常数时间操作 O(1)。
4.字符串分割:
split("\s+") 方法用于将字符串分割成单词数组,其时间复杂度为 O(n)。
5. 去重和存储:
使用 HashSet 来存储不同的整数,add() 操作平均情况下是 O(1),但在最坏情况下可能是 O(n)。
6.正则表达式处理:
正则表达式用于去除前导零,其时间复杂度取决于当前处理的字符串长度,但整体上不会超过 O(n)。
7.循环遍历:
代码中有两个主要的循环:一个用于构建 StringBuilder,另一个用于处理分割后的字符串数组。这两个循环的时间复杂度都是 O(n)。