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

Posted fdwzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了424. 替换后的最长重复字符相关的知识,希望对你有一定的参考价值。

题目:

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:
字符串长度 和 不会超过 104。

示例 1:

输入:
s = "ABAB", k = 2

输出:
4

解释:
用两个‘A‘替换为两个‘B‘,反之亦然。

示例 2:

输入:
s = "AABABBA", k = 1

输出:
4

解释:
将中间的一个‘A‘替换为‘B‘,字符串变为 "AABBBBA"。
子串 "BBBB" 有最长重复字母, 答案为 4。

 

解答:

开始没想到滑动窗口,用dfs做了半天,第20几个用例答案不对,查错也查不出来。

由于题目是问最长子串,这种题目动态规划或者滑动窗口需要着重考虑一下,因为都是当前状态都是和之前相邻的状态有关。


1.先固定左边界,右边界一直右移,直到当前区间内的需要替换的字母数大于k。

2.之后左边界右移,直到该区间需要替换的字母数小于等于k。重复1步骤。

 

问题是怎么找出某个区间内需要替换的字母数。

答案是用一个memo数组记录各字母在当前区间内的出现次数,出现最多的,我们认为它就是主要字母,其他字母都替换为它。这样总的替换次数是最少的。(其实就是贪心。)

(我之前妈蛋就是这里没想明白怎么找,结果用dfs遍历所有可能,太菜了)

 

可行的代码:

 1 class Solution {
 2 public:
 3     int characterReplacement(string s, int k) {
 4         int n=s.size();
 5         if(n==0){return 0;}
 6         int le=0,ri=0,max_cnt=0;
 7         int res=1;
 8         vector<int> cnt(26,0);
 9         while(ri<n){
10             cnt[s[ri]-A]+=1;
11             max_cnt=*max_element(cnt.begin(),cnt.end());
12             while(ri-le+1-max_cnt>k){
13                 cnt[s[le]-A]-=1;
14                 ++le;
15                 max_cnt=*max_element(cnt.begin(),cnt.end());
16             }
17             res=max(res,ri-le+1);
18             ++ri;
19         }
20         return res;    
21     }
22 };

技术图片

 

 这个写法是对的,但是还有更优解。就是每次只有右边界更新的时候,max_cnt才进行更新。

左边界右移的时候不更新。

我自己也不是特别理解原理,只能贴一个解释:

这里有个优化,不需要每次都去重新更新max_count。比如说"AAABCDEDFG" k=2,这个case,一开始A出现3次,max_count=3,但是当指针移到D时发现不行了,要移动left指针了。此时count[‘A‘]-=1,但是不需要把max_count更新为2。为什么呢? 因为根据我们的算法,当max_count和k一定时,区间最大长度也就定了。当我们找到一个max_count之后,我们就能说我们找到了一个长度为d=max_count+k的合法区间,所以最终答案一定不小于d。所以,当发现继续向右扩展right不合法的时候,我们不需要不断地右移left,只需要保持区间长度为d向右滑动即可。如果有某个合法区间大于d,一定在某个时刻存在count[t]+1>max_count,这时再去更新max_count即可。

链接:https://leetcode-cn.com/problems/longest-repeating-character-replacement/comments/69360

 

代码优化为:

 1 class Solution {
 2 public:
 3     int characterReplacement(string s, int k) {
 4         int n=s.size();
 5         if(n==0){return 0;}
 6         int le=0,ri=0,max_cnt=0;
 7         int res=1;
 8         vector<int> cnt(26,0);
 9         while(ri<n){
10             cnt[s[ri]-A]+=1;
11             max_cnt=max(max_cnt,cnt[s[ri]-A]);
12             while(ri-le+1-max_cnt>k){
13                 cnt[s[le]-A]-=1;
14                 ++le;
15             }
16             res=max(res,ri-le+1);
17             ++ri;
18         }
19         return res;    
20     }
21 };

技术图片

 

以上是关于424. 替换后的最长重复字符的主要内容,如果未能解决你的问题,请参考以下文章

leetcode424 替换后的最长重复字符 java题解

[LeetCode] 424. Longest Repeating Character Replacement

滑动窗口问题复习

LeetCode刷题总结-双指针位运算和分治法篇

LEETCODE 003 找出一个字符串中最长的无重复片段

结合两个代码片段?将用户输入的 Youtube url 转换为嵌入 url,然后将 iframe src 替换为转换后的 url