刷题(5) | 豆包MarsCode AI刷题

51 阅读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

解题思路

考虑将每个字母 'a''z' 作为可能的目标字符。对于每个目标字符,使用滑动窗口的方法,找出最长的连续子串,使得在不超过 m 次修复操作的情况下,可以将其他字符(通过修复操作)转换为目标字符。

算法流程

遍历每个可能的目标字符

将所有的字符都替换成某一个目标字符 'a''z',然后找出对该目标字符修复的最长连续子串。

滑动窗口

对于每一个目标字符,使用滑动窗口维护一个子串。窗口的左右边界由 leftright 变量表示。遍历字符串时,如果当前位置字符与目标字符不同且该位置可以修复(即 str2[right] == '1'),则增加修复操作计数。如果超过了最大允许修复次数 m,则将左边界 left 向右移动,直到修复次数不超过 m

记录最大长度

每次调整窗口时,计算当前窗口的长度,并更新最大长度。最后,遍历所有可能的目标字符,找到最大长度。

代码实现

def solution(n, m, str1, str2):
    max_length = 0  # 用于记录最终的最大长度

    # 遍历所有可能的目标字符
    for target_char in 'abcdefghijklmnopqrstuvwxyz':
        left = 0  # 滑动窗口的左边界
        count = 0  # 当前窗口内需要进行的修复操作次数

        for right in range(n):
            # 当前字符是否与目标字符相同
            if str1[right] != target_char:
                if str2[right] == '1':
                    count += 1  # 需要进行一次修复操作
                else:
                    # 当前位置无法修改,需要重置窗口
                    left = right + 1
                    count = 0
                    continue  # 跳过当前字符,开始新的窗口

            # 如果修复操作次数超过 m,移动左边界
            while count > m:
                if str1[left] != target_char and str2[left] == '1':
                    count -= 1  # 减少一次修复操作
                left += 1  # 移动左边界

            # 更新当前窗口的长度
            current_length = right - left + 1
            if current_length > max_length:
                max_length = current_length

    return max_length

if __name__ == "__main__":
    print(solution(5, 2, "abcda", "01110") == 3)
    print(solution(7, 2, "abbaccb", "1001001") == 4)
    print(solution(3, 0, "aab", "101") == 2)

总结

滑动窗口的技巧在字符串问题中非常常见,可以高效地解决类似的子串问题,尤其适合处理子串修复、删除或者替换等变动情况。