1004. Max Consecutive Ones III
1004. Max Consecutive Ones III
[Problem]
Array
Binary Search
Sliding Window
Prefix Sum
Intuition
- Interpret the question as: “Longest subarray with at most
k
zeroes”. - There is NO ACTUAL FLIPPING you need to do.
- The question is reduced to finding the maxImum subarray length with at most
k
zeroes.
Approach 1. Sliding Window
- Use a sliding window defined by
left
andright
pointers. - Increment the
right
pointer while counting zeroes in the window. - If the count of zeroes exceeds
k
, increment theleft
pointer to reduce the window size until the zero count is valid. - Update the maximum window size during the process.
Complexity Analysis
- Time Complexity: O(n)
- Each element is processed at most twice (once by
right
and once byleft
).
- Each element is processed at most twice (once by
- Space Complexity: O(1)
- No extra space used.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public int longestOnes(int[] nums, int k) {
int n = nums.length;
// start left from index `0`, and initialize maxLen to `0`
// `maxLen` is the length of longest window where the no. of zeroes <= k
int left = 0, maxLen = 0;
// iterate with the right pointer to "expand" the window
for (int right = 0; right < n; right++) {
// if a `0` is encountered, decrement `k`, which tracks the no. of zeroes allowed in the window
if (nums[right] == 0) {
k--;
}
// if the no. of zeroes in the window exceeds `k`, move the `left` pointer to shrink the window
// This ensures we always maintain at most `k` zeroes in the window
while (k < 0) {
// if the element at the `left` pointer is 0, increment `k` to "restore" a zero
if (nums[left] == 0) {
k++;
}
// move the `left` pointer forward to shrink the window
left++;
}
// update `maxLen` with the maximum window length encountered so far
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
}
Approach 2. Prefix Sum
Because the array contains only 0s
and 1s
, the sum in a given range [left, right]
represents the count of 1s
in that window.
- For example, if the sum is
4
, it means there are4
ones in that window, and the rest are zeros. The number of zeroes can be calculated as:
No. of zeroes = window_length - No. of ones
- Now, to solve the problem:
- Increment the
right
pointer to expand the window, allowing up tok
zeroes in the window. Continue expanding until there are at mostk
zeroes. - If the number of zeroes exceeds
k
, start incrementing theleft
pointer. - Incrementing
left
effectively shifts the window. Initially, onlyright
was expanding the window length, but by movingleft
, the window size becomes constant while adjusting the zero count. - Continue this process until the number of zeroes in the window becomes less than or equal to
k
.
- Increment the
Complexity Analysis
- Time Complexity: O(n)
One pass to calculate the prefix sum, and one pass to adjust the window. - Space Complexity: O(n)
Additional space for the prefix sum array.
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public int longestOnes(int[] nums, int k) {
int n = nums.length;
// initialize the prefixSum array to store cumulative sums
// prefixSum[i] will represent the sum of elements in nums[0] to nums[i-1]
int[] prefixSum = new int[n + 1];
// compute the prefix sum array
for (int i = 0; i < n; i++) {
prefixSum[i + 1] = prefixSum[i] + nums[i];
}
// start left from index `0`, and initialize maxLen to `0`
// `maxLen` is the length of longest window where the no. of zeroes <= k
int left = 0, maxLen = 0;
// iterate with the right pointer to "expand" the window
for (int right = 0; right < n; right++) {
// calculate the no. of 1s in the current window [left, right]
int numOnes = prefixSum[right + 1] - prefixSum[left];
// calculate the no. of 0s in the current window
// remember, `no. of zeros = window_length - no. of ones`
int numZeroes = (right - left + 1) - numOnes;
// if the no. of zeroes exceeds k, increment `left`
// this will shrink the window to make the no. of zeroes <= k
if (numZeroes > k) {
left++;
} else {
// if the window is valid, update `maxLen`
maxLen = Math.max(maxLen, right - left + 1);
}
}
return maxLen;
}
}
This post is licensed under CC BY 4.0 by the author.