字符替换与最长子串问题 | 豆包MarsCode AI刷题

80 阅读3分钟

问题描述

小R得到了一个由大写字母组成的字符串,长度为 n。她可以对字符串中的字符进行修改,每次操作允许将某个位置的字符修改为任意字符。例如,字符串 ABC 的第一个字符 A 改为 B,则字符串变为 BBC。她最多可以进行 k 次这样的修改。

小R想知道,通过最多 k 次修改后,字符串中由最多两种不同字母组成的最长连续子串的长度是多少。

问题分析

这是一个滑动窗口的问题,我们需要:

  1. 维护一个窗口,使其最多包含两种不同字母
  2. 在窗口内最多允许k次修改
  3. 找到满足条件的最长窗口长度

实现的代码如下:

def solution(n: int, k: int, s: str) -> int:  
    char_count = {}  
    for c in s:  
        char_count[c] = char_count.get(c, 0) + 1  
    sorted_chars = sorted(char_count.items(), key=lambda x: x[1], reverse=True)  
    if len(sorted_chars) <= 2:  
        return n  
    main_chars = {sorted_chars[0][0], sorted_chars[1][0]}   
    changes = 0  
    curr_length = 0  
    max_length = 0  
    start = 0  
    for i in range(n):  
        if s[i] in main_chars:  
            curr_length += 1  
        else:  
            if changes < k:  
                changes += 1  
                curr_length += 1  
            else:  
                while start < i and changes >= k:  
                    if s[start] not in main_chars:  
                        changes -= 1  
                    start += 1  
                    curr_length -= 1  
                if changes < k:  
                    changes += 1  
                    curr_length += 1  
                
        max_length = max(max_length, curr_length)  
    return max_length  

豆包检查后提出了两点潜在问题:

  • 在滑动窗口的逻辑中,start 指针的移动逻辑可能需要进一步检查。特别是在 while start < i and changes >= k 循环中,start 指针的移动可能会导致窗口长度不正确。
  • 具体来说,当 changes >= k 时,start 指针应该移动到下一个不在 main_chars 中的字符,而不是简单地移动一个位置。

基于此豆包给出了两点总结建议:

  • 滑动窗口的收缩逻辑可能需要进一步优化。
  • 建议使用两个指针来更清晰地管理窗口的扩展和收缩。

之后我对代码进行了修改:

def solution(n: int, k: int, s: str) -> int:  
    if n <= 2:  
        return n  
        
    def get_window_length(c1, c2):  
        # 计算使用字符c1和c2能获得的最长窗口  
        left = modifications = 0  
        max_length = 0  
        
        for right in range(n):  
            # 如果当前字符不是c1或c2,需要修改  
            if s[right] != c1 and s[right] != c2:  
                modifications += 1  
            
            # 如果修改次数超过限制,移动左窗口  
            while modifications > k:  
                if s[left] != c1 and s[left] != c2:  
                    modifications -= 1  
                left += 1  
            
            curr_length = right - left + 1  
            max_length = max(max_length, curr_length)  
            
        return max_length  
    
    # 尝试所有可能的两个字母组合  
    result = 0  
    letters = set(s)  
    for c1 in letters:  
        for c2 in letters:  
            result = max(result, get_window_length(c1, c2))  
    
    return min(n, result)  

关键点解析

  1. 滑动窗口技巧

    • 使用左右指针维护窗口
    • 动态调整窗口大小以满足条件
  2. 修改策略

    • 优先考虑必要的修改
    • 合理利用剩余的修改次数
  3. 优化思路

    • 枚举可能的两个字母组合
    • 对每种组合计算最长可能长度

总结

这道题的解决过程展示了如何将复杂问题分解为可管理的子问题,以及如何通过不同的思路来优化解决方案。滑动窗口配合状态维护的思路在类似的字符串处理问题中非常有用。