青训营X豆包MarsCode 技术训练营:小D的 abc 变换问题Python题解 | 豆包MarsCode AI 刷题

164 阅读4分钟

小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次)转变。转变规则如下:

  1. a -> "bc"
  2. b -> "ca"
  3. 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')

关键代码解释

  1. for _ in range(k): 执行 k 次转换。
  2. for char in current_str: 遍历当前字符串的每个字符并依据规则进行转换。
  3. 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过来认为自己看懂了,然后过段时间又会忘记这个题的思路,所以我觉得还是需要经常进行自己的思考,实在想不出来再借鉴一下豆包,然后也需要自己重新敲一遍代码,多多理解代码其中的含义。