求给定字符串中所有数字子串的和

发布于:2025-06-29 ⋅ 阅读:(14) ⋅ 点赞:(0)
问题分析

这道题目要求我们从一个字符串中提取所有连续的数字子串,并计算它们的总和。需要注意以下两点特殊要求:

  1. 支持负数处理:遇到’-'且后面跟着数字时,将该数字视为负数
  2. 忽略小数点:数字间的小数点(如"1.1")应被视为连续的数字"11"

例如:

  • 输入:"aA1BDSK1.1DF" → 输出:1 + 11 = 12
  • 输入:"dn12DGSs-3dgdc--1xDS" → 输出:12 + (-3) + 1 = 10
解题思路
  1. 遍历字符串:逐个字符检查
  2. 状态管理
    • 使用inNumber标记是否正在处理数字
    • 使用negative标记当前数字是否为负数
  3. 特殊字符处理
    • 遇到’-':若不在数字处理中,标记negative=true;否则作为普通字符处理
    • 遇到’.':直接忽略(视为数字的一部分)
  4. 边界处理
    • 字符串末尾可能是数字,需要特殊处理
    • 处理多位数(如"123")和前导零(如"007")
Golang代码实现

下面是Golang语言的实现方案:

package main

import (
    "fmt"
    "unicode"
)

// sumNumericSubstrings 计算字符串中所有数字子串的和(支持负数和忽略小数点)
func sumNumericSubstrings(s string) int {
    total := 0      // 总和
    currentNum := 0 // 当前正在处理的数字
    inNumber := false // 是否正在处理数字
    negative := false // 当前数字是否为负数

    for i, char := range s {
        if unicode.IsDigit(char) {
            // 遇到数字
            if !inNumber {
                // 开始新的数字
                inNumber = true
                currentNum = int(char - '0') // 字符转数字
            } else {
                // 继续构建当前数字
                currentNum = currentNum*10 + int(char-'0')
            }
        } else if char == '-' {
            // 遇到负号
            if !inNumber {
                // 如果不在数字处理中,标记为负数
                negative = true
            } else {
                // 如果正在处理数字,将当前数字累加到总和,然后开始新的负数
                if negative {
                    total -= currentNum
                } else {
                    total += currentNum
                }
                currentNum = 0
                negative = true
            }
        } else if char == '.' {
            // 遇到小数点,直接忽略(视为数字的一部分)
            continue
        } else {
            // 遇到其他非数字字符
            if inNumber {
                // 当前数字结束,根据negative标记决定加减
                if negative {
                    total -= currentNum
                } else {
                    total += currentNum
                }
                inNumber = false
                currentNum = 0
                negative = false
            }
            // 重置负号标记(如果不在数字处理中)
            negative = false
        }

        // 处理字符串最后一个字符是数字的情况
        if i == len(s)-1 && inNumber {
            if negative {
                total -= currentNum
            } else {
                total += currentNum
            }
        }
    }

    return total
}

func main() {
    // 测试示例
    fmt.Println(sumNumericSubstrings("aA1BDSK1.1DF"))          // 输出: 12
    fmt.Println(sumNumericSubstrings("dn12DGSs-3dgdc--1xDS"))  // 输出: 10

    // 更多测试用例
    fmt.Println(sumNumericSubstrings("abc"))                    // 输出: 0
    fmt.Println(sumNumericSubstrings("123456"))                 // 输出: 123456
    fmt.Println(sumNumericSubstrings("a007b012"))               // 输出: 19
    fmt.Println(sumNumericSubstrings("--12--3.4--5"))           // 输出: 12 + 34 + 5 = 51
    fmt.Println(sumNumericSubstrings("a-1.2b-3c-4.5"))          // 输出: -12 + (-3) + (-45) = -60
}
    
算法复杂度分析
  • 时间复杂度:O(n),其中n是字符串的长度。我们只需要遍历字符串一次。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。
代码解析
  1. 状态管理

    • inNumber:标记是否正在处理数字
    • negative:标记当前数字是否为负数
  2. 特殊字符处理

    • 负号(‘-’):如果在数字处理前遇到,标记为负数;如果在数字处理中遇到,将当前数字累加到总和,然后开始新的负数
    • 小数点(‘.’):直接忽略,视为数字的一部分
  3. 边界处理

    • 字符串末尾是数字时,需要将最后一个数字累加到总和
    • 连续多个负号的情况(如"–1"),只有最后一个负号会影响数字的正负性
测试用例说明
  1. "aA1BDSK1.1DF" → 1 + 11 = 12(小数点被忽略,数字连续)
  2. "dn12DGSs-3dgdc--1xDS" → 12 + (-3) + 1 = 10(支持负数和连续负号)
  3. "--12--3.4--5" → 12 + 34 + 5 = 51(连续负号和小数点的组合)
  4. "a-1.2b-3c-4.5" → -12 + (-3) + (-45) = -60(多个负数和小数点)
总结

这个算法题主要考察字符串处理和状态机设计的能力。通过一次遍历,我们可以高效地识别并累加所有数字子串,同时处理负数和忽略小数点。关键在于清晰定义状态转换逻辑,并妥善处理各种边界情况。


网站公告

今日签到

点亮在社区的每一天
去签到