小D的 abc 变换问题
问题描述
小D拿到了一个仅由 "abc" 三种字母组成的字符串。她每次操作会对所有字符同时进行以下变换:
- 将
'a'变成'bc' - 将
'b'变成'ca' - 将
'c'变成'ab'
小D将重复该操作 k 次。你的任务是输出经过 k 次变换后,得到的最终字符串。
例如:对于初始字符串 "abc",执行 2 次操作后,字符串将变为 "caababbcbcca"。
测试样例
样例1:
输入:
s = "abc", k = 2
输出:'caababbcbcca'
样例2:
输入:
s = "abca", k = 3
输出:'abbcbccabccacaabcaababbcabbcbcca'
样例3:
输入:
s = "cba", k = 1
输出:'abcabc'
解题思路
给定一个由 "abc" 组成的字符串 s,我们需要对每个字符进行多次(k次)转变。转变规则如下:
a -> "bc"b -> "ca"c -> "ab"
每次转换后,字符串长度将增长。例如,"abc" 经过一次操作后变为 "bccaab"。通过循环执行 k 次转换,我们可以生成最终的字符串。
使用暴力解决的话,就循环k次,每次都进行对应规则的转化。
代码
def solution(s: str, k: int) -> str:
current_str = s
for _ in range(k):
new_str = ""
for char in current_str:
if char == 'a':
new_str += 'bc'
elif char == 'b':
new_str += 'ca'
else:
new_str += 'ab'
current_str = new_str
return current_str
if __name__ == '__main__':
print(solution("abc", 2) == 'caababbcbcca')
print(solution("abca", 3) == 'abbcbccabccacaabcaababbcabbcbcca')
print(solution("cba", 1) == 'abcabc')
关键代码解释
for _ in range(k): 执行k次转换。for char in current_str: 遍历当前字符串的每个字符并依据规则进行转换。current_str = new_str: 更新当前字符串为新转换后的字符串。
这个循环不断替换 current_str 直到完成指定的 k 次变换。
时间空间复杂度分析
每次转换会将字符串长度扩大到原来的两倍,所以时间复杂度会呈指数增长。假设初始字符串长度为 n,那么:
- 第一次转换的长度为
2n - 第二次转换为
4n - 第
k次转换后的长度为 O(n⋅2^k)
因此,时间复杂度为 O(n⋅2^k),这会随 k 增加急剧增长。
同样地,由于 new_str 每次存储了两倍于 current_str 的内容,空间复杂度为 O(n⋅2^k),需要足够的内存来存储每一步结果。
优化:使用递归进行优化
可以使用递归来代替循环结构。递归方法的思路是定义一个函数 transform,它接受字符串和剩余转换次数 k 作为输入,如果 k == 0,则返回字符串 s;否则对每个字符递归地进行转换,直到 k 次结束。
代码
def solution(s: str, k: int) -> str:
# 缓存已经计算过的变换结果
transform_cache = {}
def transform(current_str: str, remaining_k: int) -> str:
# 如果当前字符串已经计算过,直接返回缓存中的结果
if (current_str, remaining_k) in transform_cache:
return transform_cache[(current_str, remaining_k)]
# 如果剩余变换次数为0,返回当前字符串
if remaining_k == 0:
return current_str
# 生成新的字符串
new_str = ""
for char in current_str:
if char == 'a':
new_str += 'bc'
elif char == 'b':
new_str += 'ca'
elif char == 'c':
new_str += 'ab'
# 递归调用 transform 函数
result = transform(new_str, remaining_k - 1)
# 将结果存入缓存
transform_cache[(current_str, remaining_k)] = result
return result
# 调用递归函数
return transform(s, k)
个人总结
进行暴力解法的思路很简单,直接循环k次,每次都进行新字符串的转换,这个很容易想出来,但是这样的代码最后会导致的一个问题就是会让时间复杂度非常高。 我后面又想到递归这个解决办法,但是递归在理解上有一定的难度,需要细细琢磨,递归是通过一层层调用来解决问题。 借助豆包很容易解决递归的解法,但是也确实是容易让人直接就把代码copy过来认为自己看懂了,然后过段时间又会忘记这个题的思路,所以我觉得还是需要经常进行自己的思考,实在想不出来再借鉴一下豆包,然后也需要自己重新敲一遍代码,多多理解代码其中的含义。