给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。
返回仅包含 1 的最长(连续)子数组的长度。
示例 1:
输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:
[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:
输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
提示:
1 <= A.length <= 20000
0 <= K <= A.length
A[i] 为 0 或 1
通过次数71,062提交次数119,324
请问您在哪类招聘中遇到此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/max-consecutive-ones-iii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目分析
用滑动窗口很容易可以做出来。
这篇博客主要是为了记录我对一位大神——Edward Eric在评论区写的一个非常优雅的题解的分析。
Edward Eric的代码
class Solution {//原代码是Java语言,我自己翻译成了C++语言。
public:
int longestOnes(vector<int>& nums, int k) {
int n = nums.size();
int l = 0,r = 0;
while(r<n){
if(nums[r++]==0)k--;
if(k<0&&nums[l++]==0)k++;
}
return r-l;
}
};
分析和总结
前面提到过滑动窗口是针对不必要运算和冗余运算的优化,这段代码完美体现了滑动窗口的本质之一——减少不必要运算,为什么这样说呢?因为这段代码相比于题解中的其他代码有一个特别之处:窗口不会变短。如果找到了答案——即k=0后,窗口没有必要再变短,对变短的窗口进行处理实际上就是一个不必要运算,因为变短了的窗口必然不会是正确答案。
下面分析一下这段代码的思想:
指针r和l、k实际上维护的是区间[l,r-1]内若要变成连续1数组所需要消耗k的数量。若需要消耗k的数量>=0,那么只有r往后扩展,否则r和l平移,同时平移的过程中再不断减少和恢复k的数量,若再某个区间内k>0,那么便继续扩大区间长度。
一个字,帅!