Prerequisites
Before attempting this problem, you should be comfortable with:
- Arrays - Understanding how to traverse and manipulate array elements
- Sliding Window Technique - Maintaining a dynamic window over a contiguous subarray while tracking specific conditions
- Two Pointers - Using left and right pointers to efficiently process subarrays without nested iteration
1. Brute Force
Intuition
The simplest approach is to try every possible starting position and extend the window as far as we can while allowing at most one zero to be flipped. For each starting index, we scan forward and count zeros. As long as we have seen at most one zero, the current window is valid. Once we encounter a second zero, we stop extending and record the maximum length found so far. This guarantees we consider all possible substrings but results in checking many overlapping ranges.
Algorithm
- Initialize
longestSequenceto track the maximum valid window length. - For each starting index
left, iterate through the array withright:- Count zeros encountered so far.
- If the count exceeds
1, stop expanding this window. - Otherwise, update
longestSequencewith the current window size.
- Return
longestSequence.
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
longest_sequence = 0
for left in range(len(nums)):
num_zeroes = 0
for right in range(left, len(nums)): # Check every consecutive sequence
if num_zeroes == 2:
break
if nums[right] == 0: # Count how many 0's
num_zeroes += 1
if num_zeroes <= 1: # Update answer if it's valid
longest_sequence = max(longest_sequence, right - left + 1)
return longest_sequenceTime & Space Complexity
- Time complexity:
- Space complexity: constant space used
Where is the length of the input array
nums.
2. Sliding Window
Intuition
Instead of restarting from every position, we can use a sliding window that grows and shrinks dynamically. The key insight is that we only need to shrink the window when we have more than one zero inside it. By maintaining a count of zeros in the current window, we expand by moving the right pointer and contract by moving the left pointer whenever the window becomes invalid. This way, each element is visited at most twice, making the solution linear.
Algorithm
- Initialize two pointers
leftandrightat0, along withnumZeroesto track zeros in the window. - Expand the window by moving
right:- If the element at
rightis0, incrementnumZeroes.
- If the element at
- While
numZeroesequals2(window is invalid):- If the element at
leftis0, decrementnumZeroes. - Move
leftforward to shrink the window.
- If the element at
- Update
longestSequencewith the current window size (right - left + 1). - Continue until
rightreaches the end, then returnlongestSequence.
class Solution:
def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
longest_sequence = 0
left, right = 0, 0
num_zeroes = 0
while right < len(nums): # While our window is in bounds
if nums[right] == 0: # Increase num_zeroes if the rightmost element is 0
num_zeroes += 1
while num_zeroes == 2: # If our window is invalid, contract our window
if nums[left] == 0:
num_zeroes -= 1
left += 1
longest_sequence = max(longest_sequence, right - left + 1) # Update our longest sequence answer
right += 1 # Expand our window
return longest_sequenceTime & Space Complexity
- Time complexity:
- Space complexity: constant space used
Where is the length of the input array
nums.
Common Pitfalls
Off-by-One Errors in Window Size Calculation
When calculating the window size, remember that for indices left and right, the window size is right - left + 1, not right - left. Forgetting the +1 results in consistently underreporting the maximum consecutive ones by one.
Incorrectly Handling the Zero Count Threshold
The window becomes invalid when numZeroes reaches 2 (since we can only flip one zero). A common mistake is using numZeroes > 1 in some places and numZeroes == 2 in others, leading to inconsistent behavior. Be consistent with your threshold check and ensure you shrink the window only when you have exceeded the allowed number of zeros.
Not Updating the Maximum Before Shrinking
Make sure to update the longest sequence answer at the right time. If you shrink the window first and then try to update the maximum, you might miss the optimal window size. In the sliding window approach, update the result after ensuring the window is valid, not before handling the invalid case.