Description
Given a binary array nums, return the maximum number of consecutive 1’s in the array if you can flip at most one 0.
Example 1:
Input: nums = [1,0,1,1,0]
Output: 4
Explanation:
- If we flip the first zero, nums becomes [1,1,1,1,0] and we have 4 consecutive ones.
- If we flip the second zero, nums becomes [1,0,1,1,1] and we have 3 consecutive ones.
The max number of consecutive ones is 4.
Example 2:
Input: nums = [1,0,1,1,0,1]
Output: 4
Explanation:
- If we flip the first zero, nums becomes [1,1,1,1,0,1] and we have 4 consecutive ones.
- If we flip the second zero, nums becomes [1,0,1,1,1,1] and we have 4 consecutive ones.
The max number of consecutive ones is 4.
Constraints:
1 <= nums.length <= 10^5
nums[i] is either 0 or 1.
Follow up: What if the input numbers come in one by one as an infinite stream? In other words, you can’t store all numbers coming from the stream as it’s too large to hold in memory. Could you solve it efficiently?
Solution
DP
Use dp[i][k]
to denote the consecutive 1s if we use i
as the ending, and we do k
operations. Then the transformation equation is:
d
p
[
i
]
[
k
]
=
{
1
+
max
(
d
p
[
i
−
1
]
[
:
k
]
)
,
if
n
u
m
s
[
i
]
=
=
1
1
+
d
p
[
i
−
1
]
[
k
−
1
]
,
if
n
u
m
s
[
i
]
=
=
0
\begin{aligned} dp[i][k] = \begin{cases} 1 + \max(dp[i-1][:k]), &\;\;\text{if} \;\;nums[i]==1 \\ 1 + dp[i-1][k-1], &\;\; \text{if} \;\; nums[i]==0 \end{cases} \end{aligned}
dp[i][k]={1+max(dp[i−1][:k]),1+dp[i−1][k−1],ifnums[i]==1ifnums[i]==0
Time complexity:
o
(
n
∗
k
)
o(n*k)
o(n∗k)
Space complexity:
o
(
n
∗
k
)
o(n*k)
o(n∗k)
Sliding window
Use a sliding window, make sure there are no more than one 0 inside the window.
Time complexity:
o
(
n
)
o(n)
o(n)
Space complexity:
o
(
n
)
o(n)
o(n)
Code
DP
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
dp = [[0] * 2 for _ in range(len(nums))]
# init
if nums[0] == 1:
dp[0][0] = 1
dp[0][1] = 1
else:
dp[0][0] = 0
dp[0][1] = 1
# dp
for i in range(1, len(dp)):
for k in range(2):
if nums[i] == 1:
dp[i][k] = 1 + max(dp[i - 1][:k + 1])
else:
if k - 1 < 0:
dp[i][k] = 0
else:
dp[i][k] = 1 + dp[i - 1][k - 1]
res = 0
for i in range(len(dp)):
res = max(res, max(dp[i]))
return res
Sliding window
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
left = 0
res = 0
zero_cnt = 0
for right in range(len(nums)):
# put item into window
if nums[right] == 0:
zero_cnt += 1
# shrink window if needed
while zero_cnt > 1:
if nums[left] == 0:
zero_cnt -= 1
left += 1
res = max(res, right - left + 1)
return res