A clear explanation of finding the longest streak of 1s in a binary array with a single pass.
Problem Restatement
We are given a binary array nums.
A binary array contains only:
| Value | Meaning |
|---|---|
0 | Breaks a streak |
1 | Continues a streak |
We need to return the maximum number of consecutive 1s in the array. The official problem statement asks for the maximum number of consecutive 1s in a binary array.
Input and Output
| Item | Meaning |
|---|---|
| Input | A binary integer array nums |
| Output | Length of the longest consecutive run of 1s |
| Values | Each element is either 0 or 1 |
| Constraint | The input length is positive |
Function shape:
def findMaxConsecutiveOnes(nums: list[int]) -> int:
...Examples
Example 1:
nums = [1, 1, 0, 1, 1, 1]There are two runs of 1s:
[1, 1] length 2
[1, 1, 1] length 3The longest run has length 3.
Answer:
3Example 2:
nums = [1, 0, 1, 1, 0, 1]The runs of 1s have lengths:
1, 2, 1Answer:
2First Thought: Split Into Groups
One way is to join the array into a string and split on 0.
For example:
nums = [1, 1, 0, 1, 1, 1]becomes:
"110111"Split by 0:
"11", "111"The answer is the longest piece length.
class Solution:
def findMaxConsecutiveOnes(self, nums: list[int]) -> int:
s = "".join(str(x) for x in nums)
groups = s.split("0")
return max(len(group) for group in groups)This works, but it builds extra strings. We can solve the problem directly in one scan.
Key Insight
A consecutive run of 1s continues while we keep seeing 1.
When we see 0, the current run ends.
So we only need two counters:
| Variable | Meaning |
|---|---|
current | Length of the current run of 1s |
best | Longest run seen so far |
When we see 1, increment current.
When we see 0, reset current to 0.
After every 1, update best.
Algorithm
Initialize:
current = 0
best = 0Then scan every number in nums.
If the number is 1:
current += 1
best = max(best, current)If the number is 0:
current = 0Return best.
Correctness
The variable current always stores the length of the run of consecutive 1s ending at the current position.
If the current value is 1, then the previous run extends by one, so incrementing current is correct.
If the current value is 0, then no run of 1s can end at this position, so resetting current to 0 is correct.
The variable best stores the maximum value of current seen so far. Since every run of 1s ends at some position, the algorithm considers the length of every run when updating best.
Therefore, after scanning the whole array, best is exactly the maximum number of consecutive 1s.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(n) | We scan the array once |
| Space | O(1) | Only two counters are used |
Implementation
class Solution:
def findMaxConsecutiveOnes(self, nums: list[int]) -> int:
current = 0
best = 0
for num in nums:
if num == 1:
current += 1
best = max(best, current)
else:
current = 0
return bestCode Explanation
The current streak starts at zero:
current = 0The best answer also starts at zero:
best = 0When we see a 1, the current streak grows:
current += 1Then we update the best result:
best = max(best, current)When we see a 0, the streak is broken:
current = 0After the loop, best is the longest streak.
Testing
def run_tests():
s = Solution()
assert s.findMaxConsecutiveOnes([1, 1, 0, 1, 1, 1]) == 3
assert s.findMaxConsecutiveOnes([1, 0, 1, 1, 0, 1]) == 2
assert s.findMaxConsecutiveOnes([0, 0, 0]) == 0
assert s.findMaxConsecutiveOnes([1, 1, 1]) == 3
assert s.findMaxConsecutiveOnes([0, 1, 1, 0, 1]) == 2
assert s.findMaxConsecutiveOnes([1]) == 1
assert s.findMaxConsecutiveOnes([0]) == 0
print("all tests passed")
run_tests()Test meaning:
| Test | Why |
|---|---|
[1, 1, 0, 1, 1, 1] | Main example |
[1, 0, 1, 1, 0, 1] | Multiple shorter runs |
[0, 0, 0] | No 1s |
[1, 1, 1] | Whole array is one run |
[0, 1, 1, 0, 1] | Longest run is in the middle |
[1] | Single one |
[0] | Single zero |