题目:1004. Max Consecutive Ones III
Given an array A
of 0s and 1s, we may change up to K
values from 0 to 1.
Return the length of the longest (contiguous) subarray that contains only 1s.
Example 1:
Input: A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
Output: 6
Explanation:
[1,1,1,0,0,1,1,1,1,1,1]
Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.
Example 2:
Input: A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
Output: 10
Explanation:
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.
Note:
1 <= A.length <= 20000
0 <= K <= A.length
A[i]
is0
or1
题意:
给定一个包含若干整数的数列A(仅包含数字0和1),和一个整数K,求出数列A中最长连续1的个数(可以使k个0变为1,以使最长仅包含1的数列长度最长)。
分析:
最长子序列的衍生题,步骤如下:
- 从左往右遍历序列,同时记录最左端的位置left和最右端的位置right以及[left, right]之间包含0的个数。
- 如若遍历的当前位置为0, 且当前使用0 的个数小于k,那么可以就可以把当前位置记入当前子序列区间。
- 如果上述情况下, 当前包含0的个数大于等于k,那么及说明当前子序列区间中包含的0的个数已经达到了最大,所以需要从左往右查找子序列中包含的第一个0的位置,即将包含的第一个0之前的序列去除掉,以使[ left, right]包含0的个数不足k个。
- 每次将上述问题处理之后,统计当前序列的长度right-left+1 是否为当前最大,如果是,则替换即可。
第二种方法:
- 借助两个下标,分别指向当前位置最长连续1的左右两端。
- 如果 当前位置为0的时候,那么0计数器就减1。
- 如果0计数器小于0的时候,即可说明当前包含0的个数超量,因此 这时左端点需要跟随右端点的移动而后移。
- 最后只需要返回两个端点间的距离即可。
Code & C++:
auto __ =[]()
{
std::ios::sync_with_stdio(false);
cin.tie(nullptr);
return nullptr;
}();
class Solution {
public:
int longestOnes(vector<int>& A, int k) {
int left=0, right=0, zeros=0, maxN=0;
while(right<A.size()){
if(A[right]==0){
zeros++;
}
while(zeros>k){
if(A[left]==0){
--zeros;
}
left++;
}
maxN = max(maxN, right-left+1);
right++;
}
return maxN;
}
};
Result:
Runtime: 28 ms, faster than 100.00% of C++ online submissions for Max Consecutive Ones III.
Memory Usage: 13.6 MB, less than 100.00% of C++ online submissions for Max Consecutive Ones III.
同理,python实现如下
Code & Python
class Solution:
def longestOnes(self, A: List[int], K: int) -> int:
left, right, zeros, maxlen = 0, 0, 0, 0
while right<len(A):
if A[right]==0:
zeros+=1
while zeros>K:
if A[left]==0:
zeros-=1
left+=1
maxlen = max(maxlen, right-left+1)
right+=1
return maxlen
Result:
Runtime: 220 ms, faster than 31.76% of Python3 online submissions for Max Consecutive Ones III.
Memory Usage: 13.7 MB, less than 100.00% of Python3 online submissions forMax Consecutive Ones III.
Code2 & Python
class Solution:
def longestOnes(self, A: List[int], K: int) -> int:
left, right = 0, 0
while right<len(A):
if A[right]==0:
K-=1
if K<0:
if A[left]==0:
K+=1
left+=1
right+=1
return right-left #没有加1的原因是 while的终止条件为right==len(A),也即right本身已经是有效范围的下一位了,所以不需要加1了
Result:
Runtime: 136 ms, faster than 89.32% of Python3 online submissions for Max Consecutive Ones III.
Memory Usage: 13.8 MB, less than 100.00% of Python3 online submissions forMax Consecutive Ones III.
以上两种思路 核心其实是一样的,区别在于第一种当当前序列包含0的个数超量时,即从左端开始向右查找第一个填充0的位置,并以此位置开始统计下一个最长连续序列的长度,而第二种则是当填充0的个数超量时,并不是直接在左端找到第一个0填充点,而是让当前序列的左端随右端点的移动而移动,直至遇到数字0即可,而此时左右端点间的间距一直为所求最长序列的长度,而第一种方法则是时刻保存0填充的个数不超量,并且使用一个临时变量保存所遇到的最大值。