Difficulty: Medium, Asked-in: Amazon, VMware.
Key takeaway: An excellent question to understand the idea of the sliding window. Using similar technique, we can solve several coding problems efficiently in O(n) time and O(1) space.
You are given an array of 1s and 0s, along with an integer k that represents the maximum number of allowed flips. Write a program to return the count of the maximum consecutive 1s in the array, considering that you can flip at most k 0s.
Input: X[] = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1], k = 2, Output: 8.
Explanation: We are allowed to flip a maximum of 2 zeroes. Flipping X[5] and X[7] results in 8 consecutive 1’s, which is the maximum possible under the given constraints.
Input: X[] = [1, 1, 0, 1, 0, 1, 0, 0, 1], k = 1, Output: 4.
Explanation: We are allowed to flip a maximum of 1 zero. Flipping X[2] gives us 4 consecutive 1's, which is the maximum possible under the given constraints.
A brute-force solution idea is to consider every subarray through two nested loops. For each subarray, we count the number of zeroes and return the maximum-sized subarray with k or fewer zeroes.
int maxContinuousOnes(int X[], int n, int k)
{
int maxOneCount = 0;
for (int i = 0; i < n; i = i + 1)
{
int countZeros = 0;
int j = i;
while (j < n)
{
if (X[j] == 0)
{
countZeros = countZeros + 1;
if (countZeros > k)
break;
}
j = j + 1;
}
maxOneCount = max(maxOneCount, j - i);
}
return maxOneCount;
}
def max_continuous_ones(X, n, k):
max_one_count = 0
for i in range(n):
count_zeros = 0
j = i
while j < n:
if X[j] == 0:
count_zeros = count_zeros + 1
if count_zeros > k:
break
j = j +1
max_one_count = max(max_one_count, j - i)
return max_one_count
In the worst case, we will be exploring every subarray. For this, we are running two nested loops where for every value of i, j is going from i to n-1. Total no of loop iterations = n + n -1 + n-2 …+ 1 = n(n+1)/2 = O(n²). So time complexity = O(n²)*O(1) = O(n²).
We are only using a constant number of extra variables, so space complexity = O(1).
The critical question is: Can we improve the solution further and solve this problem using a single traversal of the array? Is there some insight into the problem that could help us build a better solution? Let's think! Considering there are only 0's and 1's in the array, two scenarios may arise:
So the idea using the sliding window would be to track each window with k number of 0's and find the maximum size of such a window. How do we do this? Let's think!
The idea is to scan the array, track each window using two pointers, and count the 0s in each window. When the count of 0's is less than k, we keep moving forward in the current window by counting 0's and tracking the maximum number of 1 counts using a variable.
When the count of 0's is greater than k, we slide the left end of the current window by one forward. Before doing this, we need to update the zero count of the new window by checking whether the left end of the previous window is 0 or 1. If it is 0, then we decrement the zero count by 1.
Step 1: We initialize two variables, zeroCount and maxOneCount, to track the count of zeros in the current window and the maximum possible count of ones. zeroCount is initialized to 0, and maxOneCount is set to 0.
Step 2: We also initialize a pointer, l = 0, to track the left end of the current window and run a loop from r = 0 to n - 1 to access each window. Note: In this loop, the pointer r tracks the right end of the current window.
Step 3: By the end of the loop, we return the value stored in the variable maxOneCount.
int maxConsecutiveOne(int X[], int n, int k)
{
int zeroCount = 0;
int l = 0;
int maxOneCount = 0;
for (int r = 0; r < n; r = r + 1)
{
if (X[r] == 0)
zeroCount = zeroCount + 1;
if (zeroCount > k)
{
if (X[l] == 0)
zeroCount = zeroCount - 1;
l = l + 1;
}
maxOneCount = max(maxOneCount, r - l + 1);
}
return maxOneCount;
}
def max_consecutive_one(X, n, k):
zero_count = 0
l = 0
max_one_count = 0
for r in range(n):
if X[r] == 0:
zero_count = zero_count + 1
if zero_count > k:
if X[l] == 0:
zero_count = zero_count - 1
l = l + 1
max_one_count = max(max_one_count, r - l + 1)
return max_one_count
In the above code, we run a single loop and perform a constant number of operations at each iteration. So the time complexity = n * O(1) = O(n). As we use only a constant extra variables, the space complexity is O(1).
Enjoy learning, Enjoy coding!