Back to Arrays
Q54Question 54 of 109

Longest Subarray with Ones after Replacement (Max Consecutive Ones III)

Key Concepts
  • A variable-size sliding window counts zeros inside the window and keeps the count at most k.
  • When the zero count exceeds k, the left pointer advances until the budget is restored.
  • You never need to track which specific zeros to flip; only the count matters because all flips cost the same.
  • The widest feasible window seen during the scan is the answer.
  • Time complexity is O(N) because both pointers only move forward, and space is O(1).
  • This is the same sliding window template as character replacement string problems.

Definition

Grow the window while the zero count stays at most k; when it exceeds k, shrink from the left until the budget is restored.
  • This problem asks for the longest window in a binary array that becomes all ones after flipping at most k zeros.
  • A variable-size sliding window counts how many zeros lie inside the window.
  • The right pointer expands the window; when the zero count exceeds k, the left pointer shrinks it.
  • You only need the count of zeros, not their positions, because all flips cost the same.
  • The widest feasible window ever seen is the answer.
  • Time is O(N) and space is O(1).

At the National Bank of India, Rajesh reviews a daily on-time-payment history for a loan, where 1 means paid on time and 0 means missed. The bank's hardship policy lets him forgive at most k missed days. He wants the longest continuous clean stretch achievable after those forgiveness waivers. He slides a window across the history, forgiving misses until he runs out of budget, then tightens the left edge.

Understanding the Concepts

What is the Longest Subarray with Ones after Replacement problem?

Given a binary array of 0s and 1s and an integer k, find the length of the longest contiguous subarray that contains only 1s after you flip at most k zeros to ones. This is LeetCode 1004 (Max Consecutive Ones III).

For example, given [1, 1, 0, 0, 1, 1, 1, 0, 1] and k = 2, the longest window is 7 (flip the zeros at indices 2 and 7).

How does the sliding window work?

We keep a window with left and right boundaries and a counter for how many zeros are inside. The right pointer walks across the array. Each time it lands on a zero, we increment the counter. When the counter exceeds k, we shrink from the left until the counter returns to k.

JAVA
package com.bank.service;

public class LongestOnesService {

    /**
     * Finds the longest on-time payment streak achievable
     * after forgiving at most k missed payments.
     * Used by the National Bank of India loan-servicing team.
     */
    public static int longestOnes(int[] history, int k) {
        int left = 0;
        int zeros = 0;
        int best = 0;

        for (int right = 0; right < history.length; right++) {
            if (history[right] == 0) {
                zeros++;
            }
            while (zeros > k) {
                if (history[left] == 0) {
                    zeros--;
                }
                left++;
            }
            best = Math.max(best, right - left + 1);
        }
        return best;
    }

    public static void main(String[] args) {
        int[] history = {1, 1, 0, 0, 1, 1, 1, 0, 1};
        int k = 2;
        System.out.println("Longest clean streak with "
            + k + " waivers: " + longestOnes(history, k));
    }
}
BASH
javac -d out com/bank/service/LongestOnesService.java
java -cp out com.bank.service.LongestOnesService
TEXT
Longest clean streak with 2 waivers: 7

Why does only the zero count matter?

The key insight is that you never need to track which specific zeros to flip. Any k zeros inside the window can be flipped, and the cost is identical regardless of which ones you choose. This collapses what looks like a combinatorial choice into a plain single-counter window problem.

Why is the while loop sometimes replaced with an if?

Since the zero count only goes one over budget at a time (each step adds at most one zero), a single if that advances left once per expansion is sufficient. This variation keeps the window size monotonically non-decreasing, which is slightly different behavior but gives the same final answer.

JAVA
// Alternative: non-shrinking window variant
for (int right = 0; right < history.length; right++) {
    if (history[right] == 0) zeros++;
    if (zeros > k) {
        if (history[left] == 0) zeros--;
        left++;
    }
    best = Math.max(best, right - left + 1);
}

What are the edge cases?

Several edge cases deserve attention.

  • All ones: no zeros to flip, the answer is the array length.
  • All zeros with k >= length: flip everything, the answer is the array length.
  • All zeros with k = 0: cannot flip any, the answer is 0.
  • k larger than the number of zeros: the answer is the full array length.
  • Empty array: the answer is 0.
JAVA
package com.bank.core;

public class LongestOnesEdgeCases {
    public static void main(String[] args) {
        System.out.println(longestOnes(new int[]{1, 1, 1}, 2));    // 3
        System.out.println(longestOnes(new int[]{0, 0, 0}, 3));    // 3
        System.out.println(longestOnes(new int[]{0, 0, 0}, 0));    // 0
        System.out.println(longestOnes(new int[]{}, 5));            // 0
    }

    static int longestOnes(int[] arr, int k) {
        int left = 0, zeros = 0, best = 0;
        for (int right = 0; right < arr.length; right++) {
            if (arr[right] == 0) zeros++;
            while (zeros > k) { if (arr[left] == 0) zeros--; left++; }
            best = Math.max(best, right - left + 1);
        }
        return best;
    }
}
TEXT
3
3
0
0

What is the time and space complexity?

Time is O(N) because the right pointer advances N times and the left pointer only moves forward, so together they take at most 2N steps. Space is O(1): a single integer counter and two index variables, regardless of input size.

How is this similar to other sliding window problems?

This is the same template as the "Longest Substring with K Replacements" string problem. The only difference is the validity condition: here it is a zero count against k; there it is the count of non-majority characters against k.

DIAGRAM
| Problem | Array type | Validity condition |
|---|---|---|
| Max Consecutive Ones III | Binary array | zeros <= k |
| Longest Substring K Replacements | Character array | non-majority chars <= k |
| Longest Subarray with Sum <= K | Positive int array | sum <= k |

Can this be used in a streaming scenario?

Yes. Because the state is a single integer counter and two pointers, this algorithm can run as a streaming computation. As new payment events arrive for each loan, you update the window incrementally without re-scanning the history. The constant space makes it safe under very long histories.

What should a senior engineer know?

A senior engineer should understand these deeper aspects.

  • Non-shrinking variant: using if instead of while keeps the window size monotonically non-decreasing, which can be slightly faster but changes the invariant.
  • Binary search alternative: for each right endpoint, binary search for the leftmost position such that the window has at most k zeros, using a prefix-sum array. This is O(N log N) and uses more space but demonstrates a different technique.
  • Batch processing: in production, the linear window lets nightly batches recompute eligibility across millions of active loans within tight SLA windows.

Visual Overview

DIAGRAM
  History: [1, 1, 0, 0, 1, 1, 1, 0, 1], k=2

  ┌───────────────────────────────────────────┐
  │  right=0: val=1, zeros=0, window=[0,0]=1  │
  │  right=1: val=1, zeros=0, window=[0,1]=2  │
  │  right=2: val=0, zeros=1, window=[0,2]=3  │
  │  right=3: val=0, zeros=2, window=[0,3]=4  │
  │  right=4: val=1, zeros=2, window=[0,4]=5  │
  │  right=5: val=1, zeros=2, window=[0,5]=6  │
  │  right=6: val=1, zeros=2, window=[0,6]=7  │
  │  right=7: val=0, zeros=3 > k!             │
  │    shrink: left=0 (val=1), left=1         │
  │    shrink: left=1 (val=1), left=2         │
  │    shrink: left=2 (val=0), zeros=2, left=3│
  │    window=[3,7]=5                         │
  │  right=8: val=1, zeros=2, window=[3,8]=6  │
  └───────────────────────────────────────────┘

  Best window: [0, 6] with length 7

Key Takeaway

This problem asks for the longest contiguous subarray of a binary array that becomes all ones after flipping at most k zeros, and you solve it with a variable-size sliding window in linear time using only a single counter. The right pointer advances across the array, incrementing the zero count on each zero. When the count exceeds k, the left pointer advances until the budget is restored. The widest feasible window seen is the answer.

The clarifying insight is that you never need to track which specific zeros to flip. You only need their count, because flipping any k of them costs the same. That is what collapses a combinatorial choice into a plain single-counter window, and it is why the algorithm is linear time with constant space.

At the National Bank of India, Rajesh used this on the loan-servicing team. For each loan, the team kept a binary daily history where 1 meant the installment was paid on time and 0 meant it was missed. The hardship program allowed waiving at most k failed days in a review window. The longest continuous on-time streak achievable after those waivers determined whether the borrower qualified for a lower interest tier.

The senior-level point is that this is the same sliding window template as several string problems, just with the validity test being a zero count against k. Recognizing that shared shape lets you reuse one approach confidently across many problems, and the constant space makes it safe for streaming computation over long histories.

Remember one sentence: slide a window counting zeros, shrink when zeros exceed k, and the widest feasible window is the longest all-ones subarray after at most k flips.

---

Share
Use ← → arrow keys to navigate