AlgoMaster Logo

Max Consecutive Ones III

mediumFrequency6 min readUpdated June 23, 2026

Understanding the Problem

The problem talks about flipping zeros, but a reframing makes it easier to solve: we never need to decide which zeros to flip. We need the longest subarray that contains at most k zeros. Any subarray with at most k zeros can become all ones by flipping those zeros, so its length is a candidate answer, and the longest such subarray is the answer.

This turns the problem from "which zeros should I flip?" into finding the longest contiguous window that holds at most k zeros.

Key Constraints:

  • nums.length <= 10^5 → We need O(n log n) or better. An O(n^2) brute force will likely TLE.
  • nums[i] is 0 or 1 → Binary array, so a window only needs a single zero counter, no value bookkeeping.
  • 0 <= k <= nums.length → k can be 0 (no flips allowed) or equal to the array length (flip everything). Both edge cases need handling.

Approach 1: Brute Force

Intuition

Check every possible subarray, count the zeros in it, and if the count is at most k, record its length. The longest such subarray is the answer.

For each starting index i, extend a subarray to the right while keeping a running count of zeros. Once the count exceeds k, stop extending (a longer subarray from the same start can only have more zeros) and move to the next starting index.

Algorithm

  1. Initialize maxLen = 0
  2. For each starting index i from 0 to n-1:
    • Initialize zeroCount = 0
    • For each ending index j from i to n-1:
      • If nums[j] == 0, increment zeroCount
      • If zeroCount > k, break (no point extending further)
      • Otherwise, update maxLen = max(maxLen, j - i + 1)
  3. Return maxLen

Example Walkthrough

1i=0: expand j=0..4, zeros=2 at j=4, window=[1,1,1,0,0], maxLen=5
0
1
i
1
1
2
1
3
0
4
j
0
5
0
6
1
7
1
8
1
9
1
10
0
1/8

Code

The bottleneck is that every starting index re-scans the array from scratch. The next approach reuses the previous window instead of rebuilding it, which cuts the running time to linear.

Approach 2: Sliding Window

Intuition

Instead of restarting the scan for each starting position, maintain a window defined by two pointers, left and right. Expand the window by moving right forward. When the window holds more than k zeros, shrink from the left until it is valid again.

Removing an element from the left is cheap: when left advances past a zero, the zero count drops by one, so the count stays correct without recounting. Each element is added once (when right passes it) and removed at most once (when left passes it), which gives a linear-time algorithm.

Algorithm

  1. Initialize left = 0zeroCount = 0maxLen = 0
  2. For each right from 0 to n-1:
    • If nums[right] == 0, increment zeroCount
    • While zeroCount > k:
      • If nums[left] == 0, decrement zeroCount
      • Increment left
    • Update maxLen = max(maxLen, right - left + 1)
  3. Return maxLen

Example Walkthrough

1right=0..2: all 1s, zeroCount=0, window grows to size 3
0
1
left
1
1
2
right
1
3
0
4
0
5
0
6
1
7
1
8
1
9
1
10
0
1/8

Code

The sliding window is already O(n). The next approach drops the inner shrink loop entirely: instead of contracting the window when it becomes invalid, it slides the window forward at a fixed size. The result is the same answer with a single pointer move per step.

Approach 3: Sliding Window (Non-Shrinking)

Intuition

Once a valid window of size W exists, only a larger window can improve the answer. So instead of shrinking when the zero count exceeds k, slide the window: advance left once for each over-budget right, so both pointers move forward together and the size holds.

When right lands on a zero that pushes the count over k, move left forward by exactly one (not in a loop). If nums[left] was a zero, the count drops back to k and the window is valid again at the same size. If nums[left] was a one, the window is still one zero over budget, so it keeps sliding at a fixed size until a future left-step removes a zero. Either way the size never shrinks.

The largest window ever reached is right - left + 1 at the end, which equals n - left.

Algorithm

  1. Initialize left = 0zeroCount = 0
  2. For each right from 0 to n-1:
    • If nums[right] == 0, increment zeroCount
    • If zeroCount > k:
      • If nums[left] == 0, decrement zeroCount
      • Increment left
  3. Return right - left + 1 (which equals n - left)

Example Walkthrough

1right=0..2: all 1s, zeroCount=0, window grows to size 3
0
1
left
1
1
2
right
1
3
0
4
0
5
0
6
1
7
1
8
1
9
1
10
0
1/10

Code