不同整数的计数问题解析
问题描述
题目给定一个字符串 word,由数字和小写英文字母组成。要求统计从中提取出的不同整数的个数。
-
数字的定义:
- 连续的数字字符构成一个整数。
- 去掉前导零后,表示不同的十进制整数。
-
示例:
- 输入:
"a123bc34d8ef34",数字提取为[123, 34, 8, 34],不同的整数为{123, 34, 8},结果为 3。 - 输入:
"a1b01c001d4",数字提取为[1, 01, 001, 4],去掉前导零后,不同整数为{1, 4},结果为 2。
- 输入:
解题分析
关键点
-
数字的提取:
- 从字符串中连续提取数字,忽略字母。
- 利用遍历方法识别数字字符段。
-
不同整数的判定:
- 必须去掉前导零。
- 使用**集合(Set)**存储唯一整数。
-
时间复杂度优化:
- 字符串遍历一次 O(n)。
- 每次将数字加入集合,插入和查重操作均为 O(1)。
解题思路
为了解决这个问题,可以分为以下几步:
1. 字符串遍历
通过遍历字符串的每个字符:
- 如果当前字符是数字,将其加入当前的数字段。
- 如果遇到字母,或者是最后一个字符,结束当前的数字段。
2. 去除前导零
将每个数字段去掉前导零,转化为标准的十进制整数格式。
3. 使用集合去重
利用集合的唯一性,直接存储这些整数,自动完成去重操作。
4. 返回集合大小
最后,集合中的元素数量即为不同整数的个数。
代码详解
以下是完整的 Java 实现:
主方法
public static int solution(String word) {
// 初始化变量
int flag = 0; // 标志是否在数字段
int num = 0; // 当前构造的数字
Set<Integer> sum = new HashSet<>(); // 存储不同的整数
// 遍历字符串
for (int i = 0; i < word.length(); i++) {
flag = 0; // 每次初始化标志位
// 判断是否为数字字符
if (word.charAt(i) - '0' >= 0 && word.charAt(i) - '0' <= 9) {
// 构造数字
num = (word.charAt(i) - '0') + num * 10;
flag = 1; // 标记当前为数字段
}
// 判断是否结束当前数字段
if (flag == 1 && (i + 1 >= word.length() || Character.isLowerCase(word.charAt(i + 1)))) {
sum.add(num); // 将当前数字加入集合
num = 0; // 重置数字
}
}
// 返回集合大小
return sum.size();
}
测试方法
public static void main(String[] args) {
// 测试样例
System.out.println(solution("a123bc34d8ef34") == 3); // 输出 3
System.out.println(solution("t1234c23456") == 2); // 输出 2
System.out.println(solution("a1b01c001d4") == 2); // 输出 2
}
关键实现点解析
1. 数字识别与构造
-
每次检测字符是否为数字:
if (word.charAt(i) - '0' >= 0 && word.charAt(i) - '0' <= 9) -
当前数字段通过公式构造:
num = (word.charAt(i) - '0') + num * 10;
2. 数字段结束的判断
-
当前段结束有两种情况:
- 到达字符串末尾。
- 下一个字符是字母。
-
结束后将数字加入集合:
sum.add(num); num = 0;
3. 集合去重
-
利用集合
Set的特性自动去重,无需额外逻辑处理:Set<Integer> sum = new HashSet<>();
复杂度分析
-
时间复杂度:
- 遍历字符串:O(n)。
- 集合插入与查重:单次 O(1),最坏情况 O(n)。
总体时间复杂度为:O(n)。
-
空间复杂度:
- 使用集合存储数字,最坏情况下存储所有整数,空间复杂度为 O(m)(m为不同整数个数)。
测试与分析
测试用例 1
-
输入:
"a123bc34d8ef34" -
过程:
- 提取数字段:
[123, 34, 8, 34] - 去重后:
{123, 34, 8}
- 提取数字段:
-
输出:
3
测试用例 2
-
输入:
"t1234c23456" -
过程:
- 提取数字段:
[1234, 23456] - 去重后:
{1234, 23456}
- 提取数字段:
-
输出:
2
测试用例 3
-
输入:
"a1b01c001d4" -
过程:
- 提取数字段:
[1, 01, 001, 4] - 去重后:
{1, 4}
- 提取数字段:
-
输出:
2
优化与个人思考
-
优化方向:
- 在当前实现中,构造数字段的过程较为直接,但可以进一步优化为滑动窗口方式减少冗余判断。
- 目前每个字符只遍历一次,复杂度已很高效。
-
个人思考:
- 这类问题考验对字符串与数字间的转化和处理能力。在实际应用中,如日志解析、数据预处理等场景,也需要类似的逻辑。
- 学习到使用集合处理去重问题的便捷性,同时结合基础逻辑提升代码清晰度。
通过上述解析和实现,可以高效解决不同整数的计数问题,并对类似字符串解析问题提供借鉴意义。