AlgoMaster Logo

Max Consecutive Ones III

Last Updated: March 21, 2026

medium
4 min read

Understanding the Problem

At first glance this looks like a problem about flipping zeros. But here's the reframing that makes it much easier to solve: we don't actually need to flip anything. Instead, we need to find 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 the length of that subarray is our answer.

This reframing turns the problem from "which zeros should I flip?" into a classic sliding window problem: find the longest contiguous window with 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 tracking zeros is simple (just count them).
  • 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

The most straightforward approach: 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 our answer.

For each starting index i, we extend a subarray to the right, keeping a running count of zeros. As soon as we exceed k zeros, we stop extending 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 for every starting index, we re-scan the array from scratch. What if we could reuse the work from the previous window instead of starting over?

Approach 2: Sliding Window

Intuition

Instead of restarting the scan for each starting position, we maintain a window defined by two pointers — left and right. We expand the window by moving right forward, and when we've included too many zeros (more than k), we shrink from the left until the window is valid again.

The key insight: when we move left forward by one and that element was a zero, our zero count drops by one. So we can efficiently "undo" the effect of removing an element from the window. This way, each element is added once (when right passes over it) and removed at most once (when left passes over it), giving us an O(n) 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 approach is already O(n), but notice that when the window shrinks, it can shrink all the way back. What if we designed a window that never shrinks, only slides forward?

Approach 3: Sliding Window (Non-Shrinking)

Intuition

Once we've found a valid window of size W, we only care about finding something larger. So instead of shrinking the window when we exceed k zeros, we just slide it — move both left and right forward by one. The window size stays the same or grows, but never decreases.

When right encounters a zero that pushes us over k, we move left forward by exactly one (not in a while loop). If nums[left] was a zero, the zero 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 invalid, but that's fine — it'll just keep sliding until it becomes valid again at a larger or equal size.

The maximum window size we've ever achieved is simply right - left + 1 at the end.

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/9

Code