青训营X豆包MarsCode 技术训练营 | 豆包MarsCode AI 刷题 | Java字符串处理案例解析——统计不同整数的数目

61 阅读4分钟

在日常的编程练习中,我们常常会遇到关于字符串处理的问题,这类问题不仅能提升我们的代码编写能力,还能锻炼我们对数据结构和算法的理解。这篇文章将结合一道题目,介绍如何通过 Java 字符串处理技术,统计字符串中不同整数的个数,并分享我的思考过程和实现代码。


题目背景

问题描述

给定一个字符串 word,它由数字和小写英文字母组成。要求将字符串中的非数字字符用空格替换,然后提取其中的整数,并统计不同整数的数目。注意:

  • 整数以其不含前导零的十进制表示来区分。
  • 空字符串不算作整数。

输入输出样例

  • 输入:word = "a123bc34d8ef34",输出:3
  • 输入:word = "t1234c23456",输出:2
  • 输入:word = "a1b01c001d4",输出:2

思考过程

解决此问题需要分成几个步骤:

  1. 理解整数定义: 题目中明确要求以不含前导零的形式判断整数的不同。比如 "01""1" 被认为是同一个整数。这就要求我们在提取数字后,需要去除前导零。

  2. 处理非数字字符: 在字符串中,英文字母和其他非数字字符需要被忽略,因此用空格替换这些字符是一个自然的想法。我们可以利用正则表达式轻松实现这一点。

  3. 分割字符串并去重: 替换非数字字符后,字符串变成了一串由数字和空格组成的序列,我们可以通过空格分割提取出数字。使用集合(如 HashSet)可以有效实现去重功能。

  4. 边界条件的处理

    • 如果字符串为空,直接返回 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
    }
}

代码解析

  1. 替换非数字字符

    String replaced = word.replaceAll("[^0-9]", " ");
    

    这里使用了正则表达式 [^0-9] 匹配所有非数字字符,并用空格替换。

  2. 分割字符串

    String[] numbers = replaced.trim().split("\s+");
    

    使用空格将字符串分割为数字部分,trim() 确保去除首尾多余空格。

  3. 去重与去前导零

    uniqueNumbers.add(num.replaceFirst("^0+", ""));
    

    replaceFirst("^0+", "") 用于去除前导零,比如 "001" 会被替换为 "1"

  4. 集合存储去重: 使用 HashSet 存储去除前导零的数字,保证数字唯一性。

  5. 返回结果: 最后返回集合的大小,即为不同整数的个数。


边界条件分析

  • 输入为空字符串:返回 0
  • 输入中没有数字字符:例如 "abcd",替换后为空字符串,返回 0
  • 整数只有前导零:例如 "a001b000",输出为 1,因为前导零被去除后都为 0

测试用例

  1. 基本测试

    System.out.println(solution("a123bc34d8ef34") == 3);
    

    替换后为 " 123 34 8 34 ",数字部分为 123348,共有 3 个不同整数。

  2. 前导零处理

    System.out.println(solution("a1b01c001d4") == 2);
    

    替换后为 " 1 01 001 4 ",去除前导零后为 14,共有 2 个不同整数。

  3. 无数字字符

    System.out.println(solution("abc") == 0);
    

    替换后为空字符串,无数字,输出为 0


复杂度分析

  • 时间复杂度:O(n)O(n),其中 nn 为输入字符串的长度。正则替换和分割字符串的时间复杂度均为线性。
  • 空间复杂度:O(k)O(k),其中 kk 为不同整数的个数,用于存储集合。

总结与反思

这道题虽然看似简单,但从中可以学习到以下知识点:

  1. 正则表达式的使用场景和基本语法。
  2. 字符串处理中的边界条件分析能力。
  3. 利用集合高效去重。

对于日常开发而言,字符串处理是一项基础且重要的技能,通过不断练习类似的题目,我们可以更熟练地掌握这些技巧。

希望这篇博客对你有所帮助!欢迎留言交流你的想法~ 😊