不同整数的计数问题 | 豆包MarsCode AI刷题

60 阅读4分钟

问题描述

小R有一个字符串 word,该字符串由数字和小写英文字母组成。小R想用空格替换每一个不是数字的字符。然后,他希望统计在替换后剩下的整数中,不同整数的数目。

例如,给定字符串 "a123bc34d8ef34",替换后形成的字符串是 " 123 34 8 34",剩下的整数是 "123""34""8" 和 "34"。不同的整数有三个,即 "123""34" 和 "8"

注意,只有当两个整数的不含前导零的十进制表示不同,才认为它们是不同的整数。


测试样例

样例1:

输入:word = "a123bc34d8ef34"
输出:3

样例2:

输入:word = "t1234c23456"
输出:2

样例3:

输入:word = "a1b01c001d4"
输出:2


问题拆解

  1. 字符串替换
    题目中要求将非数字的字符替换为空格,这一步的目的是将原本的混合字符串分割成“数字块”。在Java中,我们可以通过字符遍历的方式来处理,将每个字符逐个判断是否为数字字符,非数字字符则替换为空格。
  2. 提取数字
    替换后的字符串实际上是一串用空格分隔的数字块,我们需要将这些数字块提取出来。这里可以利用字符串的 split("\s+") 方法,通过正则表达式将字符串切分成一个数字数组。
  3. 处理前导零
    提取出的数字中可能含有前导零,例如 "001" 和 "1" 实际上是相同的整数。我们可以通过将字符串转为 Integer 的方式自动去掉前导零,这一步非常关键。
  4. 统计不同整数
    利用 HashSet 的特性来存储数字,从而去除重复值。最终统计 HashSet 的大小,即为不同整数的数量。

思路解析

方法选择:字符串操作的关键

在这个问题中,核心在于字符串处理。我们有多种方法可以完成字符串的替换和分割:

  • 使用正则表达式直接替换非数字字符。
  • 手动遍历字符并拼接字符串。

最终选择使用字符遍历的方式,因为这种方式更灵活,也更适合对输入字符逐个分析的场景。

去重与数据结构

选择 HashSet 作为数据结构是一个经典且高效的做法:

  • 集合的特性保证了每个整数只会出现一次。
  • 插入和查询操作的时间复杂度为 O(1)O(1)O(1),非常高效。

代码实现与步骤

public static int solution(String word) {
    StringBuilder sb = new StringBuilder();
    for (char c : word.toCharArray()) {
        if (Character.isDigit(c)) {
            sb.append(c);
        } else {
            sb.append(' ');
        }
    }

    String[] numbers = sb.toString().trim().split("\\s+");
    Set<Integer> uniqueNumbers = new HashSet<>();

    for (String number : numbers) {
        if (!number.isEmpty()) {
            uniqueNumbers.add(Integer.parseInt(number));
        }
    }
    return uniqueNumbers.size();
}

扩展与个人思考

字符串处理的效率

  • 使用 StringBuilder 比直接操作字符串更高效,因为字符串是不可变的,每次修改都会创建新的字符串对象,而 StringBuilder 是可变的,能够减少内存开销。
  • 如果对效率要求更高,可以考虑使用 char[] 数组进行处理,进一步降低字符串操作的复杂度。

边界条件的处理

  • 空字符串:如果输入为空,结果应该为0。
  • 只有非数字字符:例如 "abcde",结果同样应该为0。
  • 连续数字块:如 "1234abc5678",程序需要能正确分割为两组数字块。

正则表达式的替代

虽然正则表达式可以解决替换和分割问题,但它的复杂性较高,且在运行效率上可能不如字符遍历的方法,尤其在输入字符串很长的情况下。我们在选择方案时,应权衡可读性与性能。

其他编程语言的实现

这种问题具有很强的通用性,除了Java外,也可以用其他语言如Python实现。Python提供了内置的字符串方法 re.subsplit,能高效地完成类似任务。


总结与收获

通过这道题目,我们复习了字符串操作、正则表达式、集合去重等基础知识,同时也锻炼了逻辑拆解能力。在实际开发中,这种问题的思路非常常见,例如提取日志中的关键数据、处理复杂的文本输入等。我们需要关注以下几点:

  1. 明确需求:先理清题目要求再下手,避免遗漏关键点。
  2. 分步处理:复杂问题通过拆分步骤逐步解决。
  3. 边界条件:考虑特殊输入的处理,确保代码鲁棒性。
  4. 效率优化:根据场景选择合适的方法和数据结构,追求高效实现。

希望这篇解析能帮助大家更好地理解这道题目的核心思路,并在今后的编程实践中有所收获!