日常刷题-字符修复问题 | 豆包MarsCode AI刷题

0 阅读3分钟

问题描述

小R有一个由小写字母组成的字符串 str1,长度为 n。字符串中有些位置的字符可以通过修复操作来修改为 a-z 中的任意一个字母,这个修复操作最多可以进行 m 次。现在,小R想知道,经过最多 m 次修复操作后,字符串中由相同字符组成的最长连续子串的最大长度是多少。

注意,str2表示哪些下标可以修改,如果为1那么就可以修改,如果为0那么就不行。


测试样例

样例1:

输入:n = 5, m = 2, str1 = "abcda", str2 = "01110"
输出:3

样例2:

输入:n = 7, m = 2, str1 = "abbaccb", str2 = "1001001"
输出:4

样例3:

输入:n = 3, m = 0, str1 = "aab", str2 = "101"
输出:2

思考

给定一个字符串 str1,长度为 n,我们可以最多进行 m 次修改操作,把字符串中的某些字符修改为任意字母。哪些位置可以修改由字符串 str2 指定,其中 '1' 表示该位置可以修改,'0' 表示该位置不能修改。我们需要找出在最多 m 次修改操作后,字符串中由相同字符组成的最长连续子串的最大长度。

解决思路

我们需要针对每个可能的字符(从 'a' 到 'z')进行尝试,看看能否通过修改操作使其形成最长的连续子串。具体步骤如下:

  1. 初始化变量:

    • max_len 用于记录最终的最大长度。
    • left 表示滑动窗口的左边界。
    • count 用于记录当前窗口中需要修改的字符数量。
  2. 遍历每个字符 c

    • 我们假设当前要将整个窗口中的字符都变成字符 c
  3. 使用滑动窗口法:

    • right 指针从左到右遍历字符串。

    • 如果 str1[right] 不是字符 c,我们检查 str2[right]

      • 如果 str2[right] == '1',表示可以修改此处的字符,增加 count
      • 如果 str2[right] == '0',表示不能修改,重置窗口,把 left 移动到 right + 1,并重置 count
  4. 调整窗口:

    • 如果 count 超过 m,意味着修改次数超过限制,需要通过移动 left 来缩小窗口,同时减少 count
  5. 更新最大长度:

    • 在每一步中计算当前窗口长度 window_len = right - left + 1,如果 window_len 大于 current_max,则更新 current_max
    • 如果 current_max 大于 max_len,则更新 max_len
  6. 返回结果:

    • 遍历所有字符后,返回 max_len 作为最终结果。

注意事项

  • 边界条件:  需要注意当滑动窗口的左边界 left 需要更新时,count 也要相应减少。
  • 性能考虑:  虽然代码需要针对每个字符都进行一次完整的遍历,但这种方法保证了在每个字符的情况下都能找到可能的最长长度。

复杂度分析

  • 时间复杂度:  对于每个字符(26个字母),我们用滑动窗口方法遍历整个字符串一次,时间复杂度为 O(n)。因此总的时间复杂度为 O(26 * n),即 O(n),因为常数因子26可以忽略。
  • 空间复杂度:  只使用了常数空间来存储变量,因此空间复杂度为 O(1)

Solution代码

def solution(n, m, str1, str2):
    max_len = 0
    for c in 'abcdefghijklmnopqrstuvwxyz':
        left = 0
        count = 0  # 修复次数
        current_max = 0
        for right in range(n):
            if str1[right] != c:
                if str2[right] == '1':
                    count += 1
                else:
                    # 无法修改,重置窗口
                    left = right + 1
                    count = 0
                    continue
            # 当修复次数超过m时,移动左指针
            while count > m:
                if str1[left] != c and str2[left] == '1':
                    count -= 1
                left += 1
            # 更新当前最大长度
            window_len = right - left + 1
            if window_len > current_max:
                current_max = window_len
        if current_max > max_len:
            max_len = current_max
    return max_len
    ```