解法:同向双指针————>滑动窗口
原因:
题目要求返回一个包含相同字母的最长字串,那就在数组中遍历找到,而又因为在暴力枚举时,会出现重复的情况,例如:在枚举以2为下标的子串时,长度结果已经在枚举下标为1的子串中记录了,因此不必做这种重复性的操作,只需定义l r两个指针,维护一个窗口进行同向的滑动即可。
思路:
因为题目说明最多可以更换k次字符,因此,只要子串中 相同字符的数量(搞一个哈希表来维护) + k > 当前字串的长度即合法,当不合法时,进行窗口的挪动,看下面具体步骤:
滑动窗口步骤:
1.left = 0,right = 0;
2.进窗口 hash[s[r]]++ ;
3.出窗口 hash[s[l]]--; l++;
4.更新结果 len = max(len,r - l + 1);
细节:
1. 上面思路说的判断条件 : 中的相同字符数量要搞清楚,要的是最多的相同字符个数,因为在窗口右移的过程中,可能后面新加进来的某个相同字符数量超过开始的那个字符的数量,那我们要做的其实是替换掉子串中出现次数少的字符。
因此:maxchar = max(maxchar,hash[s[r]]) 来维护字串内的最多相同字符个数。
2.因为上面原因的分析,发现我们要的字串的长度要满足条件取决于 判断条件,而后我们其实可以发现,l++却决于窗口内字串不合法,而r++是一直在执行的,那就说明,有两种情况:
1.l不动,r++
2.l++后,紧跟着会r++
因此,窗口大小,要么不变,要么增大,因此len = max(len,r - l + 1)操作就没有意义了。
此题l不符合判断条件仅仅移动一步,r的话会一直++,和之前的滑动窗口题目有所不同,不需要l一直++以达到条件,注意。
完整代码如下:
ps:自己写的时候,还是用了max 取len的操作,因为这样万金油。
class Solution
{
public:int characterReplacement(string s, int k) {int hash[128] = {0};int maxcount = 0,len = 0;//维护[left,right)区间的滑动窗口是最大可以替换掉的字串长度for(int l = 0,r = 0;r<s.size();r++){hash[s[r]]++;maxcount = max(maxcount,hash[s[r]]); //历史窗口中出现次数最多字母的次数。if(r - l + 1 > maxcount + k){hash[s[l]]--;l++;}len = max(len,r - l + 1);}return len;}
};