原题链接:
3. 无重复字符的最长子串 - 力扣(LeetCode)
题目解析:
题目的翻转0,意思就是把0变成1;
将题的 最多可翻转k个0 操作看成 限定范围内最多可有k个0(等价转换)
因为实际上,我们只要知道长度即可。注意,当这个子串含有的0的个数达到k个时,还能继续往后找,增加子串长度,只要没有遇到0就行,这点在设置判断条件时尤为重要。不理解可以接着往下看。
最大连续个数可以看成是最长子串问题,而最长子串问题可以用滑动窗口解决。
算法解析:
设置计数器,计算0的个数
首先数组不能越界,所以最外层循环进入条件为right<n(数组长度)
滑动窗口四步走:
1.进窗口--- 遇到0计数器++,否则忽略( ps:滑动窗口的进窗口操作是载入数据,而不是单纯的移动right指针,如果只移动了right而没有对数据进行处理,则不算进窗口。)
2.判断 --- 0个数是否大于 题目中的k (不是等于而是大于,这是因为如果在计数器的0个数等于k时就停止进窗口,并更新状态,那么就会漏情况。比如k为2 那么数组 1 1 0 0 1 1 1 1 这个数组中最长子串的长度就是8,如果是在0等于2个时就停下,那么更新的结果就会是4 还是不理解可以自己提交示例运行试试)
3.出窗口---left移动,遇到0时计数器--,直到计数器的0个数等于k个,符合题目要求为止。(所以用while循环)
4.更新状态 --- 无论是否出窗口都更新状态。只要用个max函数来判断此时的子串是否是最大长度即可
代码
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
//翻转意思是把0改成1
int zero =0,ret = 0, left = 0,right =0,n = nums.size();
while( right < n)
{
//进窗口
if(nums[right] == 0)
{
zero++;
}
//判断zero是否大于k,因为如果是刚等于,如果后面还有1,就会导致漏情况eg2
while(zero > k)
{
//出窗口
if(nums[left++]== 0)
{
zero--;
}
}
//更新
ret = max(ret,right-left+1);
right++;
}
return ret;
}
};