青训营X豆包MarsCode 刷题笔记 VI |豆包MarsCode AI刷题

43 阅读3分钟

不同整数计数问题解析与代码注解


一、问题描述

给定一个由数字和小写英文字母组成的字符串 word,将字符串中的非数字字符替换为空格后,提取出所有整数,并统计其中不同整数的数量。
注意:

  1. 整数的比较忽略前导零。
  2. 只有十进制表示不同的整数才算作不同。

二、解题思路

  1. 提取整数部分

    • 遍历字符串,连续的数字字符拼接成一个完整的整数;遇到非数字字符时,将当前拼接的整数加入集合,并清空缓冲区。
  2. 去除前导零

    • 对每个整数进行处理,去掉前导零(如 00123 转为 123)。
  3. 使用集合存储唯一值

    • 使用 Set 数据结构自动去重,最终集合的大小即为不同整数的数量。
  4. 边界处理

    • 字符串以数字结尾时,最后的数字需要单独加入集合。
    • 输入为空字符串时返回 0

三、代码实现与注释

以下是完整代码和注释:

import java.util.HashSet;
import java.util.Set;

public class Main {

    // 主解决方法
    public static int solution(String word) {
        Set<String> uniqueNumbers = new HashSet<>(); // 用于存储唯一的整数
        StringBuilder number = new StringBuilder(); // 用于拼接当前连续数字

        // 遍历字符串中的每个字符
        for (char c : word.toCharArray()) {
            if (Character.isDigit(c)) {
                // 如果是数字,加入当前数字缓冲区
                number.append(c);
            } else if (number.length() > 0) {
                // 如果遇到非数字,处理当前缓冲区中的数字
                uniqueNumbers.add(removeLeadingZeros(number.toString()));
                number.setLength(0); // 清空缓冲区
            }
        }

        // 如果缓冲区中还有未处理的数字(字符串以数字结尾)
        if (number.length() > 0) {
            uniqueNumbers.add(removeLeadingZeros(number.toString()));
        }

        return uniqueNumbers.size(); // 返回集合的大小,即不同整数的数量
    }

    // 辅助方法:去除数字字符串的前导零
    private static String removeLeadingZeros(String number) {
        int i = 0;
        // 跳过前导零
        while (i < number.length() - 1 && number.charAt(i) == '0') {
            i++;
        }
        return number.substring(i); // 返回去掉前导零后的字符串
    }

    // 测试用例
    public static void main(String[] args) {
        // 示例 1
        System.out.println(solution("a123bc34d8ef34") == 3); // 结果:3 (123, 34, 8)
        // 示例 2
        System.out.println(solution("t1234c23456") == 2); // 结果:2 (1234, 23456)
        // 示例 3
        System.out.println(solution("a1b01c001d4") == 2); // 结果:2 (1, 4)
    }
}

四、测试样例解析

样例 1:

  • 输入:"a123bc34d8ef34"
  • 处理后的整数:12334834
  • 去重后:123348
  • 输出:3

样例 2:

  • 输入:"t1234c23456"
  • 处理后的整数:123423456
  • 去重后:123423456
  • 输出:2

样例 3:

  • 输入:"a1b01c001d4"
  • 处理后的整数:1010014
  • 去除前导零后:14
  • 去重后:14
  • 输出:2

五、知识点总结

  1. 字符分类与处理

    • 使用 Character.isDigit 判断是否为数字。
    • 非数字字符作为分隔符处理,用于标记数字的结束。
  2. 前导零处理

    • 利用字符串操作跳过前导零,确保结果的唯一性。
  3. 集合去重

    • 使用 HashSet 自动去除重复元素,避免手动比较。
  4. 边界条件

    • 字符串以数字结尾时,需单独处理未完成的缓冲区内容。
    • 输入为空时,直接返回 0

六、时间复杂度分析

  1. 遍历字符串

    • 每个字符处理一次,时间复杂度为 O(n)。
  2. 前导零去除

    • 每个数字去除前导零的操作,平均复杂度为 O(1)。
  3. 集合插入

    • 使用 HashSet 存储 k 个不同整数,插入和查询的时间复杂度为 O(1)。

综合来看,算法的时间复杂度为 O(n),空间复杂度为 O(k),其中 k 是不同整数的数量。


七、总结

这道题目考察了字符串解析、集合操作和边界处理能力。通过合理分离数字和非数字字符,并使用集合存储去重的结果,能够高效解决问题。