在日常的编程练习中,我们常常会遇到关于字符串处理的问题,这类问题不仅能提升我们的代码编写能力,还能锻炼我们对数据结构和算法的理解。这篇文章将结合一道题目,介绍如何通过 Java 字符串处理技术,统计字符串中不同整数的个数,并分享我的思考过程和实现代码。
题目背景
问题描述:
给定一个字符串 word,它由数字和小写英文字母组成。要求将字符串中的非数字字符用空格替换,然后提取其中的整数,并统计不同整数的数目。注意:
- 整数以其不含前导零的十进制表示来区分。
- 空字符串不算作整数。
输入输出样例:
- 输入:
word = "a123bc34d8ef34",输出:3。 - 输入:
word = "t1234c23456",输出:2。 - 输入:
word = "a1b01c001d4",输出:2。
思考过程
解决此问题需要分成几个步骤:
-
理解整数定义: 题目中明确要求以不含前导零的形式判断整数的不同。比如
"01"和"1"被认为是同一个整数。这就要求我们在提取数字后,需要去除前导零。 -
处理非数字字符: 在字符串中,英文字母和其他非数字字符需要被忽略,因此用空格替换这些字符是一个自然的想法。我们可以利用正则表达式轻松实现这一点。
-
分割字符串并去重: 替换非数字字符后,字符串变成了一串由数字和空格组成的序列,我们可以通过空格分割提取出数字。使用集合(如
HashSet)可以有效实现去重功能。 -
边界条件的处理:
- 如果字符串为空,直接返回
0。 - 字符串中可能没有有效的整数,此时需要处理为空的情况。
- 如果字符串为空,直接返回
分步实现
下面是基于以上分析的实现代码,并在每一步给出详细说明。
import java.util.HashSet;
import java.util.Set;
class Main {
public static int solution(String word) {
// 第一步:替换所有非数字字符为空格
String replaced = word.replaceAll("[^0-9]", " ");
// 第二步:按空格分割字符串
String[] numbers = replaced.trim().split("\s+");
// 第三步:使用集合存储去重的整数
Set<String> uniqueNumbers = new HashSet<>();
for (String num : numbers) {
if (!num.isEmpty()) {
// 去除前导零
uniqueNumbers.add(num.replaceFirst("^0+", ""));
}
}
// 返回集合中不同整数的个数
return uniqueNumbers.size();
}
public static void main(String[] args) {
System.out.println(solution("a123bc34d8ef34") == 3); // 测试用例1
System.out.println(solution("t1234c23456") == 2); // 测试用例2
System.out.println(solution("a1b01c001d4") == 2); // 测试用例3
}
}
代码解析
-
替换非数字字符:
String replaced = word.replaceAll("[^0-9]", " ");这里使用了正则表达式
[^0-9]匹配所有非数字字符,并用空格替换。 -
分割字符串:
String[] numbers = replaced.trim().split("\s+");使用空格将字符串分割为数字部分,
trim()确保去除首尾多余空格。 -
去重与去前导零:
uniqueNumbers.add(num.replaceFirst("^0+", ""));replaceFirst("^0+", "")用于去除前导零,比如"001"会被替换为"1"。 -
集合存储去重: 使用
HashSet存储去除前导零的数字,保证数字唯一性。 -
返回结果: 最后返回集合的大小,即为不同整数的个数。
边界条件分析
- 输入为空字符串:返回
0。 - 输入中没有数字字符:例如
"abcd",替换后为空字符串,返回0。 - 整数只有前导零:例如
"a001b000",输出为1,因为前导零被去除后都为0。
测试用例
-
基本测试:
System.out.println(solution("a123bc34d8ef34") == 3);替换后为
" 123 34 8 34 ",数字部分为123、34和8,共有 3 个不同整数。 -
前导零处理:
System.out.println(solution("a1b01c001d4") == 2);替换后为
" 1 01 001 4 ",去除前导零后为1和4,共有 2 个不同整数。 -
无数字字符:
System.out.println(solution("abc") == 0);替换后为空字符串,无数字,输出为
0。
复杂度分析
- 时间复杂度:O(n)O(n),其中 nn 为输入字符串的长度。正则替换和分割字符串的时间复杂度均为线性。
- 空间复杂度:O(k)O(k),其中 kk 为不同整数的个数,用于存储集合。
总结与反思
这道题虽然看似简单,但从中可以学习到以下知识点:
- 正则表达式的使用场景和基本语法。
- 字符串处理中的边界条件分析能力。
- 利用集合高效去重。
对于日常开发而言,字符串处理是一项基础且重要的技能,通过不断练习类似的题目,我们可以更熟练地掌握这些技巧。
希望这篇博客对你有所帮助!欢迎留言交流你的想法~ 😊