码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-03-06 01:52:38      阅读:90      评论:0      收藏:0      [点我收藏+]

标签:cas   mic   状态   最大   public   文字   ima   pre   max   

题目:

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

注意:
字符串长度 和 不会超过 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. 替换后的最长重复字符

标签:cas   mic   状态   最大   public   文字   ima   pre   max   

原文地址:https://www.cnblogs.com/FdWzy/p/12423970.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!