小S的字符串解压缩问题 | 豆包MarsCode AI刷题

38 阅读5分钟

1. 问题回顾

问题描述

小S发现一个带有压缩格式的字符串,该字符串由数字和字母组成。每个字母前面可能会出现一个表示该字母出现次数的整数,整数按照从高位到低位排列且无前导0。如果某个字母前没有数字,表示它出现一次。小S需要将该字符串解压缩成一个仅包含字母的字符串。

例如,对于输入的字符串 a2b3cde3f,解压后应该输出 abbcccdefff


测试样例

样例1:

输入:n = 9 ,s = "a2b3cde3f"
输出:'aabbbcdeeef'

样例2:

输入:n = 10 ,s = "x44yz5mn51"
输出:'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyzzzzzmnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn'

样例3:

输入:n = 6 ,s = "adbc2d"
输出:'adbccd'

2. 代码整体思路

首先,定义了几个关键的变量:

  • temp:用于临时存储当前正在处理的字母。
  • result:用于逐步构建最终解压缩后的字符串。
  • numFlag:作为一个标志,用于判断是否正在处理数字部分,初始化为 0,表示当前不在处理数字。
  • countTemp:这是一个列表,用于存储每个数字字符转换后的整数值,以便后续计算字母出现的总次数。
  • count:用于累计计算字母根据前面数字所表示的出现总次数。
    temp = ''
    result = ''
    numFlag = 0
    countTemp = []
    count = 0

    for i in s:
        if i.isalpha() == True:
            if (numFlag != 0):
                result = result[ : -1]
                for j in range(0, len(countTemp)):
                    count += countTemp[j] * (10**(len(countTemp) - j - 1))
                result += count * temp
                count = 0
                countTemp = []
                numFlag = 0
            result += i
            temp = i
        elif i.isdigit() == True:
            countTemp.append(int(i))
            numFlag = 1
    if s[-1].isdigit() == True:
        for j in range(0, len(countTemp)):
            count += countTemp[j] * (10**(len(countTemp) - j - 1))
        result = result[ : -1]
        result += count * temp

    return result

3. 代码整体流程分析

遍历输入字符串

通过一个 for 循环来遍历输入的字符串 s 中的每个字符 i

遇到字母的情况

当 i.isalpha() == True,也就是遇到字母时:

  • 首先会检查 numFlag 是否不为 0。如果不为 0,说明之前刚刚处理完一组表示字母出现次数的数字,此时需要进行以下操作:

    • 先将 result 去掉最后一个字符,这是因为之前在处理数字时,可能已经把当前字母先添加进 result 了一次(默认出现一次的情况),现在要根据完整的数字来确定正确的添加次数,所以先去掉这一次。
    • 然后通过一个循环遍历 countTemp 列表,根据每个数字所在的位置(通过指数运算 10**(len(countTemp) - j - 1))来计算出字母应该出现的总次数,并累加到 count 中。
    • 接着将按照计算出的次数把临时存储的字母 temp 添加到 result 中,之后重置 count 为 0,清空 countTemp 列表,将 numFlag 置为 0,表示又开始处理新的字母了。
  • 最后,无论前面的条件是否满足,都要把当前遇到的字母添加到 result 中,并更新 temp 为当前字母,以便后续处理。

遇到数字的情况

当 i.isdigit() == True,也就是遇到数字时:

  • 把这个数字字符转换为整数后添加到 countTemp 列表中,同时将 numFlag 置为 1,表示当前正在处理表示字母出现次数的数字部分。
处理字符串末尾是数字的情况

在遍历完整个字符串后,还需要检查字符串的末尾是否是数字。如果 s[-1].isdigit() == True,说明最后一组数字还没有进行完整的处理来添加对应的字母到 result 中。此时,同样通过循环计算出字母的总出现次数 count,然后去掉 result 末尾已经添加过一次的字母(因为之前默认添加过一次),最后按照计算出的次数把临时存储的字母 temp 添加到 result 中。

4. 复杂度分析

时间复杂度

在函数 solution 中,主要的操作是通过一个 for 循环遍历输入字符串 s,循环的次数取决于输入字符串的长度,设输入字符串 s 的长度为 m

  • 在循环内部,对于遇到字母且 numFlag 不为 0 的情况,以及处理字符串末尾是数字的情况,都涉及到对 countTemp 列表的遍历操作。而 countTemp 列表的长度最多也就是数字部分的位数,在最坏情况下,数字部分的位数最多和字符串长度 m 相当(比如全是数字组成的字符串)。但通常情况下,数字部分的位数会远远小于字符串长度。所以这些额外的遍历操作不会改变整体的时间复杂度阶数。
  • 因此,整体的时间复杂度为O(m)O(m),即与输入字符串的长度呈线性关系。
空间复杂度

函数中定义了几个额外的变量,如 tempresultnumFlagcountTemp 和 count

  • temp 和 result 用于存储字符串相关信息,它们的长度在最坏情况下会和输入字符串长度 m 相当(比如解压缩后得到一个很长的字符串)。

  • numFlag 只是一个标志位,占用常数空间。

  • countTemp 列表用于存储数字,在最坏情况下,其长度也可能和输入字符串长度 m 相当(全是数字组成的字符串)。

  • count 用于计数,占用常数空间。

综合来看,除了输入字符串本身需要的空间外,额外开辟的空间在最坏情况下也与输入字符串长度 m 相关。所以空间复杂度为O(m)O(m)