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

85 阅读4分钟

不同整数的计数问题解析


问题描述

题目给定一个字符串 word,由数字和小写英文字母组成。要求统计从中提取出的不同整数的个数。

  1. 数字的定义:

    • 连续的数字字符构成一个整数。
    • 去掉前导零后,表示不同的十进制整数。
  2. 示例:

    • 输入:"a123bc34d8ef34",数字提取为 [123, 34, 8, 34],不同的整数为 {123, 34, 8},结果为 3。
    • 输入:"a1b01c001d4",数字提取为 [1, 01, 001, 4],去掉前导零后,不同整数为 {1, 4},结果为 2。

解题分析

关键点

  1. 数字的提取

    • 从字符串中连续提取数字,忽略字母。
    • 利用遍历方法识别数字字符段。
  2. 不同整数的判定

    • 必须去掉前导零。
    • 使用**集合(Set)**存储唯一整数。
  3. 时间复杂度优化

    • 字符串遍历一次 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<>();
    

复杂度分析

  1. 时间复杂度

    • 遍历字符串:O(n)。
    • 集合插入与查重:单次 O(1),最坏情况 O(n)。

    总体时间复杂度为:O(n)。

  2. 空间复杂度

    • 使用集合存储数字,最坏情况下存储所有整数,空间复杂度为 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


优化与个人思考

  1. 优化方向

    • 在当前实现中,构造数字段的过程较为直接,但可以进一步优化为滑动窗口方式减少冗余判断。
    • 目前每个字符只遍历一次,复杂度已很高效。
  2. 个人思考

    • 这类问题考验对字符串与数字间的转化和处理能力。在实际应用中,如日志解析、数据预处理等场景,也需要类似的逻辑。
    • 学习到使用集合处理去重问题的便捷性,同时结合基础逻辑提升代码清晰度。

通过上述解析和实现,可以高效解决不同整数的计数问题,并对类似字符串解析问题提供借鉴意义。