Definition
- Max Consecutive Ones – find the length of the longest unbroken run of the value 1 in a binary array.
- Two counters – a current counter tracks the active streak of ones; a best counter remembers the longest streak seen.
- On each 1 – increment the current counter and update best if current exceeds it.
- On each 0 – reset the current counter to zero because the streak is broken.
- Complexity – O(n) time, O(1) space, single pass with no extra data structures.
The National Bank of India records whether each day had a successful end-of-day settlement for Rajesh's account: 1 for success, 0 for failure. Operations wants the longest streak of consecutive successful days as a reliability metric. A clerk walks through the days once, counting how many successes in a row right now, and whenever that current streak beats the best streak, the best is updated. A single failed day resets the current streak to zero.
Understanding the Concepts
What is the Max Consecutive Ones problem?
Given a binary array containing only 0s and 1s, find the length of the longest contiguous subarray of all 1s. This is one of the simplest linear scan problems and a natural introduction to the sliding window family.
package com.bank.service;
public class MaxConsecutiveOnes {
public static int findMaxConsecutiveOnes(int[] nums) {
int current = 0;
int best = 0;
for (int num : nums) {
if (num == 1) {
current++;
if (current > best) best = current;
} else {
current = 0;
}
}
return best;
}
public static void main(String[] args) {
int[] settlementDays = {1, 1, 0, 1, 1, 1, 0, 1};
System.out.println("Longest success streak: " + findMaxConsecutiveOnes(settlementDays));
}
}
Longest success streak: 3
Why does the count-and-reset approach work?
A run of ones is only ever extended by seeing another one immediately after, and it is only broken by a zero. The current counter exactly measures the length of the run ending at the present position, and taking the maximum over all positions gives the longest run anywhere in the array.
// Walkthrough: [1, 1, 0, 1, 1, 1, 0, 1]
// Index 0: num=1, current=1, best=1
// Index 1: num=1, current=2, best=2
// Index 2: num=0, current=0
// Index 3: num=1, current=1
// Index 4: num=1, current=2
// Index 5: num=1, current=3, best=3
// Index 6: num=0, current=0
// Index 7: num=1, current=1
// Final best: 3
Why update best on every one instead of on every zero?
Updating best right after incrementing on each 1 is always correct. Some people update best only when they hit a 0, but then they must remember to also update once more after the loop in case the array ends in a run of ones. Updating on every 1 avoids that end-of-array special case entirely.
// WRONG: update only on 0, forgetting end-of-array
for (int num : nums) {
if (num == 1) current++;
else {
best = Math.max(best, current); // updates here
current = 0;
}
}
// BUG: if array ends with ones, best may not include the last streak
// Fix: best = Math.max(best, current); after the loop
// BETTER: update on every 1, no post-loop fix needed
if (num == 1) {
current++;
if (current > best) best = current;
}
How does this generalize to the K-flip version?
The Max Consecutive Ones III problem allows flipping at most K zeros to ones and asks for the longest run. That is solved with a sliding window that counts zeros in the window. The plain problem is the K=0 special case.
package com.bank.service;
public class MaxConsecutiveOnesIII {
public static int longestOnes(int[] nums, int k) {
int left = 0, zeros = 0, best = 0;
for (int right = 0; right < nums.length; right++) {
if (nums[right] == 0) zeros++;
while (zeros > k) {
if (nums[left] == 0) zeros--;
left++;
}
best = Math.max(best, right - left + 1);
}
return best;
}
public static void main(String[] args) {
int[] days = {1, 1, 0, 1, 1, 1, 0, 1};
System.out.println("With 1 flip: " + longestOnes(days, 1)); // 6
System.out.println("With 0 flips: " + longestOnes(days, 0)); // 3 (same as plain)
}
}
With 1 flip: 6
With 0 flips: 3
What are the edge cases?
An empty array has no ones, so the answer is zero. An array of all ones returns the full length. An array of all zeros returns zero. A single-element array returns 1 if it is a 1, or 0 if it is a 0.
package com.bank.service;
public class MaxConsecutiveEdgeCases {
public static void main(String[] args) {
System.out.println(MaxConsecutiveOnes.findMaxConsecutiveOnes(new int[]{})); // 0
System.out.println(MaxConsecutiveOnes.findMaxConsecutiveOnes(new int[]{1,1,1})); // 3
System.out.println(MaxConsecutiveOnes.findMaxConsecutiveOnes(new int[]{0,0,0})); // 0
System.out.println(MaxConsecutiveOnes.findMaxConsecutiveOnes(new int[]{1})); // 1
System.out.println(MaxConsecutiveOnes.findMaxConsecutiveOnes(new int[]{0})); // 0
}
}
0
3
0
1
0
What about input validation?
The array is expected to contain only 0s and 1s. In a defensive implementation you might validate each element, but for an interview problem the contract is trusted. For a boolean-valued stream you could use a boolean array or a BitSet and the same counting logic applies.
// Defensive version:
for (int num : nums) {
if (num != 0 && num != 1) throw new IllegalArgumentException("Not binary: " + num);
// ... same counting logic
}
What are common mistakes?
The most common mistake is forgetting to update best after the loop when updating only on zeros, which misses a run that extends to the end of the array.
// WRONG: misses trailing run
int current = 0, best = 0;
for (int num : nums) {
if (num == 1) current++;
else { best = Math.max(best, current); current = 0; }
}
// Missing: best = Math.max(best, current);
// Input [1,1,1] returns best=0 instead of 3
// CORRECT: update on every 1
if (num == 1) { current++; best = Math.max(best, current); }
When should you use this technique?
Use the count-and-reset pattern for any longest-streak problem on a sequence with a binary condition. In banking, this applies to computing reliability metrics like the longest streak of successful settlement days or the longest period without a fraud alert.
package com.bank.service;
public class SettlementReliability {
public static void main(String[] args) {
int[] monthlySettlements = {1,1,1,0,1,1,1,1,1,0,1,1};
int streak = MaxConsecutiveOnes.findMaxConsecutiveOnes(monthlySettlements);
System.out.println("Longest monthly success streak: " + streak + " months");
}
}
Longest monthly success streak: 5 months
What should a senior engineer know?
A senior engineer should recognize that this is the K=0 case of the sliding-window Max Consecutive Ones III problem. Mentioning the generalization shows depth in an interview. The early-termination optimization (if best + remaining <= best, stop) is rarely worth the check overhead for this simple scan.
What are common interview follow-up questions?
- Interviewers commonly ask:
- What if you can flip at most K zeros? (Sliding window counting zeros.)
- What if the input is a stream, not an array? (Same count-and-reset, no random access needed.)
- Can you do it without branching? (current = current * num + num, best = max(best, current).)
- Time and space? (O(n) time, O(1) space.)
Visual Overview
Input: [1, 1, 0, 1, 1, 1, 0, 1]
Walk through:
┌───┬───┬───┬───┬───┬───┬───┬───┐
│ 1 │ 1 │ 0 │ 1 │ 1 │ 1 │ 0 │ 1 │
└───┴───┴───┴───┴───┴───┴───┴───┘
c=1 c=2 c=0 c=1 c=2 c=3 c=0 c=1
b=1 b=2 b=2 b=2 b=3
c = current streak
b = best streak
Answer: best = 3 (positions 3-5)
Generalization to K-flip sliding window:
┌───────────────────────────────┐
│ [1, 1, 0, 1, 1, 1, 0, 1] │
│ ├── window (K=1) ──┤ │
│ left=0 right=5 │
│ zeros=1 (within budget) │
│ width=6 → best=6 │
└───────────────────────────────┘
Key Takeaway
Max Consecutive Ones finds the longest unbroken run of 1s in a binary array with a single pass and two counters. A current counter measures the run of ones ending at the position you are looking at, and a best counter remembers the longest run seen. On each 1 you increment the current counter and update the best. On each 0 you reset the current counter to zero because the streak is broken.
The small but real detail is to update best on every 1 rather than only on zeros. Updating only on zeros requires a post-loop fix to catch a trailing run of ones that never hits a zero, which is easy to forget. Updating on every 1 avoids that edge case entirely.
The natural extension is the version where you may flip at most K zeros to ones, which is a sliding window problem: grow the right edge, count zeros, and shrink the left edge when the zero count exceeds K. The plain problem is the K=0 case, and recognizing that connection shows the interviewer you understand the general pattern.
In the operations team at the National Bank of India, Rajesh's daily settlement history is a binary array, and the team reports the longest streak of consecutive successful days as a reliability metric. The single-pass count-and-reset approach handles years of daily data in constant memory, and the sliding-window generalization answers management's what-if about allowing a small number of excused failures.
Remember one sentence: count the current run, update the best on every 1, and reset on every 0.
---