Minimum Operations for a Continuous Segment of Ones
Last Updated :
29 Nov, 2023
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:
C++
#include <iostream>
#include <string>
#include <algorithm>
#include <climits>
using namespace std;
int min_operations( int N, string S, int X) {
int pref[N];
pref[0] = 1;
for ( int i = 1; i < N; i++) {
pref[i] = pref[i - 1];
if (S[i] != S[i - 1]) {
pref[i]++;
}
}
int ans = INT_MAX;
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);
}
}
return ans;
}
int main() {
int N = 7;
string S = "1011011" ;
int X = 5;
cout << min_operations(N, S, X) << endl;
return 0;
}
|
Java
public class GFG {
public static void main(String[] args)
{
int N = 7 ;
String S = " 1011011 ";
int X = 5 ;
System.out.println(min_operations(N, S, X));
}
public static int min_operations( int N, String S, int X)
{
int [] pref = new int [N];
pref[ 0 ] = 1 ;
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;
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 );
}
}
return ans;
}
}
|
Python3
def min_operations(N, S, X):
pref = [ 0 ] * N
pref[ 0 ] = 1
for i in range ( 1 , N):
pref[i] = pref[i - 1 ]
if S[i] ! = S[i - 1 ]:
pref[i] + = 1
ans = float ( 'inf' )
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 )
return ans
if __name__ = = "__main__" :
N = 7
S = "1011011"
X = 5
print (min_operations(N, S, X))
|
C#
using System;
class Program
{
static int MinOperations( int N, string S, int X)
{
int [] pref = new int [N];
pref[0] = 1;
for ( int i = 1; i < N; i++)
{
pref[i] = pref[i - 1];
if (S[i] != S[i - 1])
{
pref[i]++;
}
}
int ans = int .MaxValue;
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);
}
}
return ans;
}
static void Main( string [] args)
{
int N = 7;
string S = "1011011" ;
int X = 5;
Console.WriteLine(MinOperations(N, S, X));
}
}
|
Javascript
function minOperations(N, S, X) {
const pref = new Array(N);
pref[0] = 1;
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;
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);
}
}
return ans;
}
const N = 7;
const S = "1011011" ;
const X = 5;
console.log(minOperations(N, S, X));
|
Time Complexity: O(N), where N is the length of input string S.
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...