字符修复问题题解 | 豆包MarsCode AI刷题

47 阅读3分钟
问题描述

有一个小写字母组成的字符串str,字符串长度为n;字符串中某些位置可以执行修复操作:将这个位置的字符,替换为a~z中的一个字符;这个修复操作最多可以执行m次;现在想知道修复之后,字符串 str由相同字符组成的子串最大长度是多少

输入格式

每个样例有三行:

  • 第一行是整数 n 和 m,分别表示字符串长度和最多操作次数;(1≤n≤2000,0≤m≤20001≤n≤2000,0≤m≤2000)
  • 第二行是字符串 str
  • 第三行是长度为 n 的 01 字符串,0 表示该位置的字符无法修改,1 表示该位置的字符可以修改;
输出格式

每个样例一行,输出修复之后由相同字符组成的子串最大长度;

第一次思考,我忽略了一个边界问题,我把第一个字符提前计入计数范围了,所以导致错误。后来经过参考其他人的答案以及经过MarsCode的帮助,我得到了成功的解决答案。

数据结构选择
  • 字符串:用于存储输入的字符串 str
  • 字符数组:用于存储哪些位置的字符可以被修改(canModify)。
算法步骤
  1. 遍历目标字符:

    • 对于每个字符 target_char 从 'a' 到 'z',尝试将其作为目标字符。这一步的目的是为了找到以每个字符为目标字符时,能够得到的最长连续子串。
  2. 滑动窗口法:

    • 使用两个指针 left 和 right 来表示当前窗口的左右边界。
    • 初始化 left 为 0,modifications 为 0。
  3. 扩展窗口:

    • 遍历字符串 str,对于每个字符 str[right]

      • 如果 str[right] 不是目标字符且可以修改(canModify[right] == '1'),则增加 modifications 计数。
      • 如果 str[right] 不是目标字符且不能修改(canModify[right] == '0'),则重置窗口,将 left 移动到 right + 1,并重置 modifications 为 0。
  4. 收缩窗口:

    • 如果 modifications 超过 m,则收缩窗口,移动 left 指针直到 modifications 不超过 m。 在收缩窗口时,如果 str[left] 不是目标字符且可以修改(canModify[left] == '1'),则减少 modifications 计数。
  5. 更新最大长度:

    • 计算当前窗口的长度 right - left + 1,并更新最大长度 max_length
详细代码
def solution(n, m, str, canModify):
    max_length = 0
    for target_char in 'abcdefghijklmnopqrstuvwxyz':
        left = 0
        modifications = 0 

        for right in range(n):
            if str[right] != target_char:
                if canModify[right] == '1':
                    modifications += 1
                else:
                    left = right + 1
                    modifications = 0
                    continue
            while modifications > m:
                if str[left] != target_char and canModify[left] == '1':
                    modifications -= 1
                left += 1
            max_length = max(max_length, right - left + 1)
    return max_length


if __name__ == "__main__":
    # Add your test cases here

    print(solution(5, 2, "abcda", "01110") == 3)
    print(solution(7, 2, "abbaccb", "1001001") == 4)
    print(solution(3, 0, "aab", "101") == 2)
总结

这个问题是滑动窗口和双指针的经典应用。滑动窗口技巧非常适合这种寻找连续子数组或子串的问题。

  • 核心思想:使用滑动窗口法来动态调整窗口大小,以找到最大长度的相同字符子串。
  • 时间复杂度:O(26 * n),其中 26 是字母表的大小,n 是字符串的长度。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。