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相当(比如全是数字组成的字符串)。但通常情况下,数字部分的位数会远远小于字符串长度。所以这些额外的遍历操作不会改变整体的时间复杂度阶数。 - 因此,整体的时间复杂度为,即与输入字符串的长度呈线性关系。
空间复杂度
函数中定义了几个额外的变量,如 temp、result、numFlag、countTemp 和 count。
-
temp和result用于存储字符串相关信息,它们的长度在最坏情况下会和输入字符串长度m相当(比如解压缩后得到一个很长的字符串)。 -
numFlag只是一个标志位,占用常数空间。 -
countTemp列表用于存储数字,在最坏情况下,其长度也可能和输入字符串长度m相当(全是数字组成的字符串)。 -
count用于计数,占用常数空间。
综合来看,除了输入字符串本身需要的空间外,额外开辟的空间在最坏情况下也与输入字符串长度 m 相关。所以空间复杂度为。