链接:1004. 最大连续1的个数 III - 力扣(LeetCode)
题解:
滑动窗口基本解题思路:
- 进窗口
- 判断
- 出窗口
- 更新结果(该步骤顺序不固定,可能在进窗口时更新结果,也可能在判断成立时更新结果,也有可能在判断条件结束之后更新结果)
滑动窗口本质上是从暴力解法优化而来的,本题本质上就是查找0个数不超过k的最大子串,暴力算法就是枚举出所有字串,并从中筛选出0个数不超过k的所有子串,取最大的子串。
优化1:暴力算法以某个元素为开头枚举子串时,如果枚举到0个数已经超过k的子串了,那么就没有必要继续向后枚举了,因为接下来的所有以该元素开头的子串中0的个数一定都是超过k的,可以直接进入下一轮枚举,以下一个元素作为字串开头来枚举。例如有数组: [1,1,1,0,0,0,1,1,1,1,0],k=2,枚举到子串111000时,0的个数超过k,继续向后枚举1110001、11100011等的所有子串中0的个数都是超过k的。
优化2:以下一个元素作为子串开头,进入下一轮枚举时,也没有必要从从头开始枚举,例如有数组:[0,1,1,0,0,0,1,1,1,1,0],k=2,当枚举到子串01100时,0的个数超过了k,直接进行下一轮枚举从第二个元素1开始枚举,直接从1100开始枚举,因为我们已经知道01100中有几个0了,进行下一轮枚举时仅仅是相当于去除了原本的首元素,所以可以根据首元素是否为0计算剩下的子串中0的个数。
class Solution {
public:
int longestOnes(vector<int>& nums, int k) {
int ans=INT_MIN;
int n=nums.size();
int flag=0;
for(int left=0,right=0;right<n;right++)
{
if(nums[right]==0) flag+=1;//进窗口
while(flag>k)//判断
{
if(nums[left]==0) flag-=1;//出窗口
left++;
}
ans=max(ans,right-left+1);//更新结果
}
return ans;
}
};