Given two integers N, X, and a binary string S of length N, find the minimum number of operations to make a continuous segment of length X containing all 1s. In one operation, we can select an index i (0<= i < S.length()) and flip all the bits in range [0, i]. Ie. 0 to 1 and 1 to 0.
Examples:
Input: N = 5, S = 10101, X = 3
Output: 2
Explanation:
- First operation: Select i = 3 and flip the segment [0, 3] of S, then S = 01011
- Second operation: Select i = 2 and flip the segment [0, 2] of S, then S = 10111
A continuous segment of length X = 3 has been created, which is from range [2, 4] of S = 10111.
Input: N = 7, S = 1011011, X = 5
Output: 2
Explanation:
- First operation: Select i = 4 and flip the segment [0, 4] of S, then S = 0100111
- Second operation: Select i = 3 and flip the segment [0, 3] of S, then S = 1011111
A continuous segment of length X = 5 has been created, which is from range [2, 6] of S = 1011111
Approach: The problem can be solved by using the following approach:
The problem can be solved using prefix sum array. Let’s break S into contiguous blocks of zeros and ones. Notice, that for some substring, that starts at position L and ends at position R, the number of flip operations required to make it all ones is related to the number of blocks in it. The idea is to check for every window of size X, starting from the end of the string S. For every window, flip the blocks greedily to get all 1s in the window. Let’s say that some window A of length X consists of Z ‘blocks’. Then, there are 2 cases:
- If A ends with ‘1’, then we don’t need to flip the last block (as the last block has 1s in it) so the answer is Z-1.
- A ends with ‘0’, then we need to flip the last block (as the last block has 0s in it) so the answer is Z.
Let’s return to our initial problem. We need to make a window of length X all 1’s. First, let’s create a Prefix sum array of the number of blocks at index i, where pref[i] = number of blocks in the substring S[0…i]. Now iterate over S and for each window, we check the number of blocks in this window and if the window ends with 1, subtract 1. Find the minimum of all such windows to get the answer.
Steps to solve the problem:
- Initialize a prefix array let say pref[] of length N.
- Initialize Pref[0] = 1.
-
Run a loop for i = 1 to N-1:
- pref[i] = pref[i-1].
- If S[i] != S[i-1], then pref[i]++.
- Create a variable ans to count the minimum number of operations required and initialize it to INT_MAX.
-
Run a loop for i = 0 to i <= (N – K):
- If S[i+K-1] == 1, then ans = min(ans, pref[i+K-1] – pref[i])
- Else ans = min(ans, pref[i+K-1] – pref[i] + 1)
- Return ans.
Code to implement the approach:
#include <iostream> #include <string> #include <algorithm> #include <climits> using namespace std;
// Method to return the minimum operations required int min_operations( int N, string S, int X) {
// Declaring Prefix array
int pref[N];
// Initializing the first element of the array as 1
pref[0] = 1;
// Implementing the approach discussed
for ( int i = 1; i < N; i++) {
pref[i] = pref[i - 1];
if (S[i] != S[i - 1]) {
pref[i]++;
}
}
int ans = INT_MAX;
// Iterating over every window of size X
for ( int i = 0; i <= N - X; i++) {
if (S[i + X - 1] == '1' ) {
ans = min(ans, pref[i + X - 1] - pref[i]);
} else {
ans = min(ans, pref[i + X - 1] - pref[i] + 1);
}
}
// Returning the minimum number of operations required
return ans;
} int main() {
// Inputs
int N = 7;
string S = "1011011" ;
int X = 5;
// Printing the minimum operations
cout << min_operations(N, S, X) << endl;
return 0;
} |
// Java code to implement the approach public class GFG {
// Driver Class
public static void main(String[] args)
{
// Inputs
int N = 7 ;
String S = " 1011011 ";
int X = 5 ;
// Printing the minimum operations
System.out.println(min_operations(N, S, X));
}
// Method to return the minimum
// operations required
public static int min_operations( int N, String S, int X)
{
// declaring Prefix array
int [] pref = new int [N];
// Initializing first element
// of array as 1
pref[ 0 ] = 1 ;
// Implementing the approach discussed
for ( int i = 1 ; i < N; i++) {
pref[i] = pref[i - 1 ];
if (S.charAt(i) != S.charAt(i - 1 ))
pref[i]++;
}
int ans = Integer.MAX_VALUE;
// Iterating over every window
// of size X
for ( int i = 0 ; i <= N - X; i++) {
if (S.charAt(i + X - 1 ) == '1' ) {
ans = Math.min(ans,
pref[i + X - 1 ] - pref[i]);
}
else {
ans = Math.min(ans, pref[i + X - 1 ]
- pref[i] + 1 );
}
}
// Returning the minimum number
// of operations required
return ans;
}
} |
# Function to return the minimum operations required def min_operations(N, S, X):
# Initializing a prefix array
pref = [ 0 ] * N
# Initializing the first element of the array as 1
pref[ 0 ] = 1
# Implementing the approach discussed
for i in range ( 1 , N):
pref[i] = pref[i - 1 ]
if S[i] ! = S[i - 1 ]:
pref[i] + = 1
ans = float ( 'inf' )
# Iterating over every window of size X
for i in range (N - X + 1 ):
if S[i + X - 1 ] = = '1' :
ans = min (ans, pref[i + X - 1 ] - pref[i])
else :
ans = min (ans, pref[i + X - 1 ] - pref[i] + 1 )
# Returning the minimum number of operations required
return ans
# Main function if __name__ = = "__main__" :
# Inputs
N = 7
S = "1011011"
X = 5
# Printing the minimum operations
print (min_operations(N, S, X))
|
using System;
class Program
{ // Method to return the minimum operations required
static int MinOperations( int N, string S, int X)
{
// Declaring Prefix array
int [] pref = new int [N];
// Initializing the first element of the array as 1
pref[0] = 1;
// Implementing the approach discussed
for ( int i = 1; i < N; i++)
{
pref[i] = pref[i - 1];
if (S[i] != S[i - 1])
{
pref[i]++;
}
}
int ans = int .MaxValue;
// Iterating over every window of size X
for ( int i = 0; i <= N - X; i++)
{
if (S[i + X - 1] == '1' )
{
ans = Math.Min(ans, pref[i + X - 1] - pref[i]);
}
else
{
ans = Math.Min(ans, pref[i + X - 1] - pref[i] + 1);
}
}
// Returning the minimum number of operations required
return ans;
}
static void Main( string [] args)
{
// Inputs
int N = 7;
string S = "1011011" ;
int X = 5;
// Printing the minimum operations
Console.WriteLine(MinOperations(N, S, X));
}
} |
// JavaScript code for the above approach // Function to return the minimum operations required function minOperations(N, S, X) {
// Declaring Prefix array
const pref = new Array(N);
// Initializing the first element of the array as 1
pref[0] = 1;
// Implementing the approach discussed
for (let i = 1; i < N; i++) {
pref[i] = pref[i - 1];
if (S[i] !== S[i - 1]) {
pref[i]++;
}
}
let ans = Number.MAX_VALUE;
// Iterating over every window of size X
for (let i = 0; i <= N - X; i++) {
if (S[i + X - 1] === '1' ) {
ans = Math.min(ans, pref[i + X - 1] - pref[i]);
} else {
ans = Math.min(ans, pref[i + X - 1] - pref[i] + 1);
}
}
// Returning the minimum number of operations required
return ans;
} // Inputs const N = 7; const S = "1011011" ;
const X = 5; // Printing the minimum operations console.log(minOperations(N, S, X)); // This code is contributed by Abhinav Mahajan (abhinav_m22) |
2
Time Complexity: O(N), where N is the length of input string S.
Auxiliary Space: O(N)