L4. Max Consecutive Ones III | Two Pointers and Sliding Window
This chapter covers the classic Max Consecutive Ones III problem, exploring its progression from a naive brute-force approach to an optimal sliding window solution without an inner shrinking loop.
1. Problem Statement and Objective
We are given a binary array (nums) containing only 0s and 1s, and an integer K. Our objective is to find the maximum number of consecutive 1s we can get in the array if we are allowed to flip at most K zeros.
Real-Life Analogy: The Window of Tolerance
Analogy: Imagine looking at a long train of boxcars where some cars are empty (
0) and some are full (1). You have a special budget of tarps (Kflips) to cover up empty cars so the entire section looks packed. Your goal is to slide a viewing window across the train to find the longest contiguous block of cars you can make look entirely full using at mostKtarps.
2. Converting the Problem Statement
When faced with phrasing like "maximum consecutive ones with at most K zeros flipped," we can reframe the problem into a standard subarray pattern:
Conceptually: The problem is identical to finding the longest subarray that contains at most
Kzeros.
If a contiguous window has zero count , it is a valid candidate. Our goal is to maximize the length of this window (j - i + 1).
3. Naive Brute Force Approach ()
The most intuitive approach is to generate all possible subarrays, count the number of zeros in each, and track the maximum length where zero count .
Brute Force Code Implementation
class Solution {
public int longestOnes(int[] nums, int k) {
int maxLength = 0;
int n = nums.length;
for (int i = 0; i < n; i++) {
int zeros = 0;
for (int j = i; j < n; j++) {
if (nums[j] == 0) {
zeros++;
}
if (zeros <= k) {
maxLength = Math.max(maxLength, j - i + 1);
} else {
break; // Stop expanding if zeros exceed K
}
}
}
return maxLength;
}
}
- Time Complexity: in the worst case, as we iterate through possible starting and ending points.
- Space Complexity: auxiliary space.
4. Better Approach: Standard Sliding Window with Inner While Loop ()
To achieve linear time complexity, we use a Two-Pointer / Sliding Window approach. We maintain a window bounded by a left pointer (L) and a right pointer (R), along with a running count of zeros.
Execution Flow Walkthrough
- Expand
Rto the right, incorporating elements into the window. - If
nums[R] == 0, increment ourzeroscount. - If
zeros > K, the window is invalid. We must shrink the window from the left (L++) untilzerosdrops back to . - At each valid step, calculate window length
R - L + 1and updatemaxLength.
Standard Sliding Window Code
class Solution {
public int longestOnes(int[] nums, int k) {
int maxLen = 0, l = 0, r = 0, zeros = 0;
int n = nums.length;
while (r < n) {
if (nums[r] == 0) {
zeros++;
}
// Shrink window if zeros exceed K
while (zeros > k) {
if (nums[l] == 0) {
zeros--;
}
l++;
}
if (zeros <= k) {
maxLen = Math.max(maxLen, r - l + 1);
}
r++;
}
return maxLen;
}
}
- Time Complexity: because in the worst case, both
RandLtraverse the array. - Space Complexity: .
5. Optimal Approach: Eliminating the Inner While Loop ()
An insightful optimization for elite interviews is eliminating the inner while loop entirely.
The Core Insight
Notice that we are searching for the maximum length. Once our window reaches a maximum size, we never actually need the window size to shrink. Even if zeros > K, we can simply slide the window forward with a fixed maximum size, only letting L move forward by at most one position when a zero is encountered.
Key Rule: We do not allow the window to shrink below its historical maximum size.
Lonly advances step-by-step alongsideRwhen violations occur, preserving the max length found so far until a larger valid window can be formed.
6. Complete Optimal Code Implementation
Here is the fully optimized Java implementation running in strict time without an inner while loop:
class Solution {
public int longestOnes(int[] nums, int k) {
int maxLen = 0, l = 0, r = 0, zeros = 0;
int n = nums.length;
while (r < n) {
if (nums[r] == 0) {
zeros++;
}
// If zeros exceed K, shift left pointer by exactly 1
if (zeros > k) {
if (nums[l] == 0) {
zeros--;
}
l++;
}
if (zeros <= k) {
maxLen = Math.max(maxLen, r - l + 1);
}
r++;
}
return maxLen;
}
}
7. Complexity Comparison Table
8. Summary and Key Takeaways
- Problem Translation: Finding the maximum consecutive ones with at most
Kzeros flipped is equivalent to finding the longest subarray with at mostKzeros. - Two-Pointer Foundation: Sliding window techniques utilize a left (
L) and right (R) pointer to dynamically evaluate contiguous segments. - Window Expansion: The right pointer (
R) greedily expands the window to test larger possible lengths. - Constraint Management: When zero counts exceed
K, window adjustments maintain validity. - Optimization Principle: To achieve strict time without an inner loop, prevent the window size from shrinking; instead, slide it forward at a fixed maximum size once a peak is established.
- Space Efficiency: All sliding window solutions achieve auxiliary space complexity by operating directly on the input array.