题目描述
题目分析
每次操作都对每个字符同时进行如下变换:
'a' -> 'bc''b' -> 'ca''c' -> 'ab'
初始字符串的每个字符在变换后都会“裂变”成一串新的字符,这些新字符又会在下次变换中进一步“分裂”。这个过程就像递归一样,不断增长,越来越大。
暴力解法——穷尽膨胀之路
想法
我们可以直接按照题意,模拟每次的裂变操作。对于每一轮的变换,我们生成一个新的字符串,通过将原字符串中的每个字符按规则替换成新的字符串段来更新它。这种方法直白易懂,但是随着操作次数增多,字符串的长度会以指数方式增长,计算量也会迅速飙升。
步骤
- 将字符串中的每个字符依次替换为对应的变换结果。
- 更新字符串,重复步骤1,共执行 次。
代码实现(python)
def solution(s: str, k: int) -> str:
# 将字符串转换为列表
s = list(s)
# 进行 k 次变换
for _ in range(k):
# 初始化新的字符串列表
new_s = []
# 对当前字符串中的每个字符进行变换
for char in s:
if char == 'a':
new_s.extend(['b', 'c'])
elif char == 'b':
new_s.extend(['c', 'a'])
elif char == 'c':
new_s.extend(['a', 'b'])
# 更新字符串列表
s = new_s
# 将列表转换回字符串并返回
return ''.join(s)
分析
这个方法在早期操作次数(即k较小)时还可以运行得动,但随着k增加,字符串长度会成倍暴涨,直接超出计算机的承受范围。这就像在给怪物喂养无限饲料一样,很快它就会变成无边无际的“字符海啸”——所以,暴力法很容易超时或耗尽内存。
当然,其实我暴力法提交上去直接过了,所以接下来的都不用看了
优化解法——解析递归结构,掌控裂变规律
既然暴力破解太恐怖,我们可以换个思路,通过分析找出变换的规律。我们的目标是从指数增长中找出规律,用一个“公式”直接计算出最后的结果,而不是一步步模拟。
发现规律
观察前几次变换的结果,我们可以看出一点规律性:
- 初始字符串
"abc"。 - 第 1 次变换得到
"bccaab". - 第 2 次变换得到
"caababbcbcca".
可以发现,这种“裂变”中包含了递归结构!经过 k 次变换的结果,其实可以看作是一个递归展开的结果。实际上,每个字符的变化模式会在每次操作中自我重复和膨胀。因此我们可以通过预计算变换后的字符串片段,而不必每次都重新生成整个字符串。
优化思路
我们可以通过动态规划或递归缓存每个字符的变换结果,在操作前先计算每个字符在 k 次变换后的结果,然后直接拼接这些结果!
def solution(s: str, k: int) -> str:
# 递归缓存的字典,用于存储每个字符在 k 次变换后的结果
memo = {}
# 定义递归函数,用来计算字符经过 k 次变换后的结果
def abc_transform_optimized(char: str, k: int) -> str:
# 递归终止条件
if k == 0:
return char
# 如果已经计算过,直接返回缓存的结果
if (char, k) in memo:
return memo[(char, k)]
# 根据当前字符选择对应的变换,并递归求解
if char == 'a':
result = abc_transform_optimized('b', k - 1) + abc_transform_optimized('c', k - 1)
elif char == 'b':
result = abc_transform_optimized('c', k - 1) + abc_transform_optimized('a', k - 1)
else: # char == 'c'
result = abc_transform_optimized('a', k - 1) + abc_transform_optimized('b', k - 1)
# 缓存结果
memo[(char, k)] = result
return result
# 计算初始字符串中每个字符经过 k 次变换后的结果并拼接
transformed_result = ''.join(abc_transform_optimized(char, k) for char in s)
return transformed_result
代码解释
- 递归缓存:
memo是一个字典,用于缓存每个字符在 k 次变换后的结果,避免重复计算。 - 递归求解:通过递归调用,每次根据字符变换规则,将变换次数 k 递减直至 0(即不再变换)。
- 拼接结果:初始字符串的每个字符经过 k 次变换的结果,最终拼接成最后的字符串。
时间复杂度分析
这个优化方法极大减少了重复计算,通过记忆化缓存每个字符的变换结果,我们在大多数情况下可以避免指数增长。虽然最终结果依然会很大,但相比暴力法,我们只需计算少量的关键字符变换。