备战秋招60天算法挑战,Day18

题目链接: https://leetcode.cn/problems/longest-repeating-character-replacement/

视频题解: https://www.bilibili.com/video/BV1zf421d7Ui/

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

题目描述

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

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

举个例子:

cpp 复制代码
输入:s = "AABABBA", k = 1
输出:4
解释:
将中间的一个'A'替换为'B',字符串变为 "AABBBBA"。
子串 "BBBB" 有最长重复字母, 答案为 4。
可能存在其他的方法来得到同样的结果。

视频题解

替换后的最长重复字符

思路来源

思路来源

思路解析

本题是一道比较经典的滑动窗口问题,目标是在字符串s找到最长的一个窗口 ,满足最多替换k个字母,窗口就可以变成所有字母都是相同的,这个窗口的长度就是我们要找的答案。

定义left = 0right = 0来表示窗口的左右边界,res来保存结果,哈希表u_charCount保存当前窗口中所有字母出现的频率。窗口的长度为right - left + 1窗口中字母出现的最高频率为maxCount。所以right - left + 1 - maxCount就是当前窗口最多要替换的字母数right - left + 1 - maxCount小于等于k[left, right]就是我们要找的一个候选窗口。

上图中,[left,right]组成的窗口中出现频率最高的字母为A,所以此时maxCount = 3,只需要把B替换成A就可以满足窗口就中所有字母都是相同的。

问题的关键是左右边界如何滑动,窗口滑动策略如下:

  1. right - left + 1 - maxCount <= k时找到以当前right为右边界的候选窗口,更新结果res = max(res, right - left + 1)right向右滑动并更新hashu_charCount[s[right]]++和当前窗口中字母的最高频率maxCount = max(maxCount, u_charCount[s[right]]),直到right - left + 1 - maxCount > k
  2. right - left + 1 - maxCount > k时未找到以当前right为右边界候选窗口,left向右滑动,更新hashu_charCount[s[left]]--,直到right - left + 1 - maxCount <= k

根据上面的策略我们可以获得以s任意位置为右边界(枚举右边界)的所有候选窗口,只需要把其中最长的一个窗口的长度返回即可。

有些同学会有疑问,为啥left向右滑动时只更新了u_charCount,却没有更新maxCount

这是因为left向右滑动时不会出现比当前res更长的候选窗口,并且此时maxCount不会增大。想获得比当前res更长的候选窗口,必须保证rightmaxCount都是相比之前变大的,只有right右滑的时候才会有更长的候选窗口出现,所以left向右滑动时没必要更新maxCount。当然想更新也是可以的,多几行代码,只是没有必要。

C++代码

cpp 复制代码
class Solution {
public:
    int characterReplacement(string s, int k) {
        //统计滑动窗口中每个字符出现的次数
        unordered_map<char, int> u_charCount;
        int res = 0;
        int left = 0, right = 0;
        //维护滑动窗口中字符出现的最大次数
        int maxCount = 0;
        int s_len = s.length();
        while (right < s_len) {
            u_charCount[s[right]] += 1;
            maxCount = max(maxCount, u_charCount[s[right]]);
            //当最少的操作数大于k,改变左边界,寻找以当前right为右边界的窗口
            while (right - left + 1 - maxCount > k) {
                u_charCount[s[left]] -= 1;
                ++left;
            }
            //更新满足条件的最大窗口
            res = max(res, right - left + 1);
            ++right;
        }
        return res;
    }
};

java代码

java 复制代码
class Solution {
    public int characterReplacement(String s, int k) {
        // 统计滑动窗口中每个字符出现的次数
        Map<Character, Integer> charCount = new HashMap<>();
        int res = 0;
        int left = 0, right = 0;
        // 维护滑动窗口中字符出现的最大次数
        int maxCount = 0;
        int sLen = s.length();
        while (right < sLen) {
            charCount.put(s.charAt(right), charCount.getOrDefault(s.charAt(right), 0) + 1);
            maxCount = Math.max(maxCount, charCount.get(s.charAt(right)));
            // 当最少的操作数大于k,改变左边界,寻找以当前right为右边界的窗口
            while (right - left + 1 - maxCount > k) {
                charCount.put(s.charAt(left), charCount.get(s.charAt(left)) - 1);
                left++;
            }
            // 更新满足条件的最大窗口
            res = Math.max(res, right - left + 1);
            right++;
        }
        return res;
    }
}

python代码

python 复制代码
class Solution:
    def characterReplacement(self, s: str, k: int) -> int:
        # 统计滑动窗口中每个字符出现的次数
        char_count = defaultdict(int)
        res = 0
        left = 0
        right = 0
        # 维护滑动窗口中字符出现的最大次数
        max_count = 0
        s_len = len(s)
        while right < s_len:
            char_count[s[right]] += 1
            max_count = max(max_count, char_count[s[right]])
            # 当最少的操作数大于k,改变左边界,寻找以当前right为右边界的窗口
            while right - left + 1 - max_count > k:
                char_count[s[left]] -= 1
                left += 1
            # 更新满足条件的最大窗口
            res = max(res, right - left + 1)
            right += 1
        return res

复杂度分析

时间复杂度: leftright只需要遍历一遍字符串,对u_charCount的操作都是常量时间复杂度,所以整体的时间复杂度是O(n) ,其中n是字符串的长度。

空间复杂度: 需要使用一个hash表,所以空间复杂度是O(26) ,即O(1)

相关推荐
Roy_Sashulin1 分钟前
基于AI的Java编程平台
java·开发语言·人工智能·sashulin·deepseek
工业互联网专业4 分钟前
基于Python的黑龙江旅游景点数据分析系统的实现_flask+spider
python·flask·vue·毕业设计·源码·课程设计·spider
旖-旎7 分钟前
二分查找(山脉数组的峰顶索引)(5)
c++·算法·leetcode·二分查找·力扣·双指针
大傻^8 分钟前
Spring AI Alibaba 企业级实战:从0到1构建智能客服系统
java·人工智能·后端·spring·springaialibaba
阿贵---10 分钟前
单元测试在C++项目中的实践
开发语言·c++·算法
进击的小头11 分钟前
第14篇:MPC控制案例——无人机高度控制
python·算法·无人机
贼爱学习的小黄13 分钟前
NC BIP增加按钮
java
短剑重铸之日13 分钟前
《ShardingSphere解读》11 解析引擎:SQL 解析流程应该包括哪些核心阶段?(上)
java·后端·spring·shardingsphere·分库分表
2401_8914821716 分钟前
C++中的事件驱动编程
开发语言·c++·算法
Javatutouhouduan17 分钟前
Netty进阶指南:基础+中级+高级+架构行业运用+源码分析
java·netty·java面试·网络io·后端开发·java程序员·互联网大厂