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

136 阅读2分钟

问题背景

有一个由大写字母组成的字符串长度为n,现在可以对字符串中的字符进行修改:每次允许将某个位置的字符修改为任意字符,比如说将字符串ABC第1个字符A改为B,则字符串变成BBC;这个操作最多可以执行k次,现在想知道修改之后,字符串中由最多两种字母组成的子串最大长度。

代码分析

solution 方法

这个方法的核心是使用滑动窗口的技术,遍历所有可能的字母对,找到最多修改 k 次后,能得到的最长由两种字母组成的子串。

java
复制代码
public static int solution(int n, int k, String inp) {
    int maxLen = 0;
    
    // 尝试每一对字符作为子串的字符
    for (char c1 = 'A'; c1 <= 'Z'; c1++) {
        for (char c2 = 'A'; c2 <= 'Z'; c2++) {
            if (c1 == c2) continue; // 同一字符对跳过

            int left = 0, right = 0;
            int count1 = 0, count2 = 0;
            int modifications = 0;

            while (right < n) {
                // 处理右指针移动,更新计数
                if (inp.charAt(right) == c1) count1++;
                else if (inp.charAt(right) == c2) count2++;
                else modifications++; // 若当前字符既不是 c1 也不是 c2,需要修改

                // 若修改次数超过 k,收缩窗口
                while (modifications > k) {
                    if (inp.charAt(left) == c1) count1--;
                    else if (inp.charAt(left) == c2) count2--;
                    else modifications--;
                    left++; // 缩小窗口,从左侧移出
                }

                // 更新最大长度
                maxLen = Math.max(maxLen, right - left + 1);
                right++; // 向右扩展窗口
            }
        }
    }
    
    return maxLen;
}

主要思路

  1. 遍历所有字符对:首先,尝试所有可能的字符对 (c1, c2),其中 c1c2 是子串中可能的两种字符。从字符 AZ 逐一尝试每一对字符。如果两个字符相同,直接跳过。

  2. 滑动窗口:对每一对字符 (c1, c2),使用滑动窗口来寻找符合条件的最大子串。窗口通过两个指针 leftright 来表示,right 逐渐向右扩展,left 向右收缩。

    • 更新窗口:如果当前窗口中的字符是 c1c2,就分别增加 count1count2。如果字符既不是 c1 也不是 c2,则需要计入修改次数 modifications
    • 收缩窗口:当 modifications 超过 k 时,我们通过移动左指针 left 来收缩窗口,直到 modifications 不再超过 k。此时,窗口内的字符全部可以通过不超过 k 次修改变成 c1c2
    • 更新最大长度:每次右指针移动时,更新最大子串长度 maxLen
  3. 返回结果:最终返回通过最多 k 次修改得到的最大长度。