• 424. 替换后的最长重复字符 ●●


    424. 替换后的最长重复字符 ●●

    描述

    给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符,并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。

    在执行上述操作后,返回包含相同字母的最长子字符串的长度

    示例

    输入:s = “AABABBA”, k = 1
    输出:4
    解释:
    将中间的一个’A’替换为’B’,字符串变为 “AABBBBA”。
    子串 “BBBB” 有最长重复字母, 答案为 4。

    题解

    1. 双指针 1

    用一个一维数组存储窗口内各字母的出现次数,每次以左边界上的字母为固定字母(即不同字母替换成该字母),右指针逐个往右移动,当无法再替换时,左指针右移,并更新当前的固定字母;

    注意,因为本解法每次都以左边界字母为固定字母,所以还需要考虑左边界之前的字母被替换后的长度,

    比如 s = “ACBBB”,k = 2;正确结果为 5;若不考虑 front ,则结果为 3。

    class Solution {
    public:
        int characterReplacement(string s, int k) {
            vector<int> cnts(26, 0);
            int n = s.length(), ans = 0;
            int l = 0, rest = k;
            cnts[s[0]-'A'] = 1;				// 初始左边界
            for(int r = 1; r < n; ++r){
                if(s[r] != s[l]) --rest;	// 替换操作,--rest
                ++cnts[s[r]-'A'];			// 统计频次
                while(rest < 0){			// 替换失败
                    --cnts[s[l]-'A'];		
                    ++l;					// 移动左指针
                    rest = k - ((r-l+1) - cnts[s[l]-'A']));	// 更新固定字母为左边界字母,(r-l+1)-cnts[s[l]-'A'] 表示当前窗口下需替换字母的个数
                }
                int front = min(rest, l);		// 考虑替换前面的字母
                ans = max(ans, r-l+1+front);	// 更新最大值
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2. 双指针 2

    枚举字符串中的每一个位置作为右端点,然后找到其最远的左端点的位置,满足该区间内除了出现次数最多的那一类字符之外,剩余的字符(即非最长重复字符)数量不超过 k 个。

    这样我们可以想到使用双指针维护这些区间,每次右指针右移,如果区间仍然满足条件,那么左指针不移动,否则左指针至多右移一格,保证区间长度不减小(保持不变或增大)

    虽然这样的操作会导致部分区间不符合条件,即移动左指针后,该区间内非最长重复字符超过了 k 个(maxSame发生改变但可能未更新)。
    但是这样的区间也同样不可能对答案产生贡献(直到移动右指针出现频次更高的字母)。当我们右指针移动到尽头,左右指针对应的区间的长度必然对应一个长度最大的符合条件的区间。

    每次区间右移,我们更新右移位置的字符出现的次数,然后尝试用它更新重复字符出现次数的历史最大值,最后我们使用该最大值计算出区间内非最长重复字符的数量,以此判断左指针是否需要右移即可。

    class Solution {
    public:
        int characterReplacement(string s, int k) {
            vector<int> cnts(26, 0);
            int n = s.length();
            int l = 0, r = 0, maxSame = 0;
            for(; r < n; ++r){
                ++cnts[s[r]-'A'];
                maxSame = max(maxSame, cnts[s[r]-'A']);	// 更新最大频次,出现更大频次时才有效
                if(k < (r-l+1) - maxSame){		        // 替换失败
                    --cnts[s[l]-'A'];			        // 移动左指针,缩小窗口(最大总长度此时不变)
                    ++l;
                }
            }                                           // for 循环中 r 多走一步,结束时 r = n
            return r-l;							        // 窗口大小保证不减小,最大符合条件的窗口长度
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
  • 相关阅读:
    iPhone 15分辨率,屏幕尺寸,PPI 详细数据对比 iPhone 15 Plus、iPhone 15 Pro、iPhone 15 Pro Max
    《uni-app》表单组件-Input组件
    springboot整合redis
    宝塔Node部署nuxt3
    走进JVM的内存模型
    SpringBoot3基础:最简项目示例
    状压dp+二分
    容器中的nginx暴露一个端口部署多个功能的网站
    注意力机制
    Python笔记 之 闭包及装饰器
  • 原文地址:https://blog.csdn.net/qq_19887221/article/details/125628393