Given a string S containing 0s and 1s of length N with X, the task is to output the minimum operations required to convert S into either all 1s or 0s. The operation is defined as, taking two different indices i and j (1-based indexing), such that they give equal remainder when dividing from X, then update Si = Si⊕Sj.
Examples:
Input: N = 4, X = 2, S = “1100”
Output: 2
Explanation:
- First operation: i = 1 and j = 3 as (i%X == j%X == 1). So, update S1 = S1⊕S3 = 1. Then S = 1110
- Second operation: i = 2 and j = 4 as (i%X == j%X == 0). So, update S2 = S2⊕S4 = 1. Then S = 1111. Now all the characters are turned into 1. Therefore, the minimum number of operations required is 2.
Input: N = 6, X = 4, S = “100101”
Output: 6
Explanation: It can be verified that, If operations are performed optimally, Then the minimum operations required will be 6.
Approach: Implement the idea below to solve the problem
Idea:
The problem is based on the Bitwise Concept and can be solved using some observations.
XOR of same characters is 0 and XOR of different characters is 1. We can do XOR operations on particular set of characters.
For Example: If X = 2, then we can do XOR on 1st, 3rd, 5th.. or 2nd, 4th, 6th… and so on.
There can be two cases: Either we can make all character to ones or all characters to zeroes.
- If we want to make all characters in a set to 1: then there should to at least one ‘1’ in that set. If not, then it is impossible to make all characters equal to ‘1’.
- If we want to make all characters in a set to 0: then if the number of ‘1’ in that set is even, then the number of operations are half of the number of ‘1’ else we have to add 2 more operations to make the one remaining ‘1’ in that set to ‘0’ using some other ‘0’ in that set by XORing the ‘0’ with ‘1’ two times.
ie. [1,0] -> 1 ^ 0 = 1; [1,1] -> 1 ^ 1 = 0; [0,0].
It takes one operation to convert [1,0] to [1,1] and one operation to convert [1,1] to [0,0]. So, it takes two operations to convert [1,0] to [0,0].
Steps were taken to solve the problem:
- Create a variable let say min1
- Create a boolean array let say vis[] of length N
-
Run a loop for i = 0 to i < N and follow below mentioned steps under the scope of loop:
-
If (!vis[i])
- one = 0
- zero = 0
-
Run a loop for for j = i to j < N with increment j += X and follow below mentioned steps under the scope of loop:
- vis[j] = true
-
If (S[j] == 0)
- zero++
-
Else
- one++
-
If (one == 0)
- min1 = INT_MAX
- break the loop
-
Else
- min1 += zero
-
If (!vis[i])
- initialize vis[] to new boolean array of same length
- Declare a variable let say min2
-
Run a loop for i = 0 to i < N and follow below mentioned steps under the scope of loop:
-
If (!vis[i])
-
one = 0
-
Run a loop for j = i to j < N with incrementing j += X and follow below mentioned steps under the scope of loop:
- vis[j] = true
-
If (S[j] == 1)
- one++
-
If (one % 2 == 0)
- min2 += one / 2
-
Else
- min2 += (one / 2) + 2
-
Run a loop for j = i to j < N with incrementing j += X and follow below mentioned steps under the scope of loop:
-
one = 0
-
If (!vis[i])
- Output min(min1, min2)
Implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
using namespace std;
// Method to output the minimum number of operations void Min_Operations( int N, int X, char S[]) {
// Approach for all ones
int min1 = 0;
vector< bool > vis(N, false );
for ( int i = 0; i < N; i++) {
if (!vis[i]) {
int one = 0;
int zero = 0;
for ( int j = i; j < N; j += X) {
vis[j] = true ;
if (S[j] == '0' )
zero++;
else
one++;
}
if (one == 0) {
min1 = INT_MAX;
break ;
} else
min1 += zero;
}
}
// Approach for all zeros
vis = vector< bool >(N, false );
int min2 = 0;
for ( int i = 0; i < N; i++) {
if (!vis[i]) {
int one = 0;
for ( int j = i; j < N; j += X) {
vis[j] = true ;
if (S[j] == '1' )
one++;
}
if (one % 2 == 0)
min2 += one / 2;
else
min2 += (one / 2) + 2;
}
}
cout << min(min1, min2) << endl;
} int main() {
// Inputs
int N = 4;
int X = 2;
char S[] = "1100" ;
// Function call
Min_Operations(N, X, S);
return 0;
} |
// Java code to implement the approach import java.io.*;
import java.util.*;
// Driver Class class GFG {
// Driver Function
public static void main(String[] args)
{
// Inputs
int N = 4 ;
int X = 2 ;
char [] S = (" 1100 ").toCharArray();
// Function call
Min_Operations(N, X, S);
}
// Method to output the minimum number
// of operations
public static void Min_Operations( int N, int X,
char [] S)
{
// Approach for all ones
int min1 = 0 ;
boolean [] vis = new boolean [N];
for ( int i = 0 ; i < N; i++) {
if (!vis[i]) {
int one = 0 ;
int zero = 0 ;
for ( int j = i; j < N; j += X) {
vis[j] = true ;
if (S[j] == '0' )
zero++;
else
one++;
}
if (one == 0 ) {
min1 = Integer.MAX_VALUE;
break ;
}
else
min1 += zero;
}
}
// Approach for all zeros
vis = new boolean [N];
int min2 = 0 ;
for ( int i = 0 ; i < N; i++) {
if (!vis[i]) {
int one = 0 ;
for ( int j = i; j < N; j += X) {
vis[j] = true ;
if (S[j] == '1' )
one++;
}
if (one % 2 == 0 )
min2 += one / 2 ;
else
min2 += (one / 2 ) + 2 ;
}
}
System.out.println(Math.min(min1, min2));
}
} |
# Method to output the minimum number of operations def min_operations(N, X, S):
# Approach for all ones
min1 = 0
vis = [ False ] * N
for i in range (N):
if not vis[i]:
one = 0
zero = 0
for j in range (i, N, X):
vis[j] = True
if S[j] = = '0' :
zero + = 1
else :
one + = 1
if one = = 0 :
min1 = float ( 'inf' )
break
else :
min1 + = zero
# Approach for all zeros
vis = [ False ] * N
min2 = 0
for i in range (N):
if not vis[i]:
one = 0
for j in range (i, N, X):
vis[j] = True
if S[j] = = '1' :
one + = 1
if one % 2 = = 0 :
min2 + = one / / 2
else :
min2 + = (one / / 2 ) + 2
print ( min (min1, min2))
# Inputs N = 4
X = 2
S = "1100"
# Function call min_operations(N, X, S) # This code is contributed by shivamgupta0987654321 |
//code by flutterfly using System;
class GFG
{ // Method to output the minimum number of operations
static void MinOperations( int N, int X, char [] S)
{
// Approach for all ones
int min1 = 0;
bool [] vis = new bool [N];
for ( int i = 0; i < N; i++)
{
if (!vis[i])
{
int one = 0;
int zero = 0;
for ( int j = i; j < N; j += X)
{
vis[j] = true ;
if (S[j] == '0' )
zero++;
else
one++;
}
if (one == 0)
{
min1 = int .MaxValue;
break ;
}
else
min1 += zero;
}
}
// Approach for all zeros
vis = new bool [N];
int min2 = 0;
for ( int i = 0; i < N; i++)
{
if (!vis[i])
{
int one = 0;
for ( int j = i; j < N; j += X)
{
vis[j] = true ;
if (S[j] == '1' )
one++;
}
if (one % 2 == 0)
min2 += one / 2;
else
min2 += (one / 2) + 2;
}
}
Console.WriteLine(Math.Min(min1, min2));
}
static void Main()
{
// Inputs
int N = 4;
int X = 2;
char [] S = { '1' , '1' , '0' , '0' };
// Function call
MinOperations(N, X, S);
}
} |
// Method to output the minimum number of operations function minOperations(N, X, S) {
// Approach for all ones
let min1 = 0;
let vis = new Array(N).fill( false );
for (let i = 0; i < N; i++) {
if (!vis[i]) {
let one = 0;
let zero = 0;
for (let j = i; j < N; j += X) {
vis[j] = true ;
if (S[j] === '0' ) {
zero++;
} else {
one++;
}
}
if (one === 0) {
min1 = Infinity;
break ;
} else {
min1 += zero;
}
}
}
// Approach for all zeros
vis = new Array(N).fill( false );
let min2 = 0;
for (let i = 0; i < N; i++) {
if (!vis[i]) {
let one = 0;
for (let j = i; j < N; j += X) {
vis[j] = true ;
if (S[j] === '1' ) {
one++;
}
}
if (one % 2 === 0) {
min2 += one / 2;
} else {
min2 += (one / 2) + 2;
}
}
}
console.log(Math.min(min1, min2));
} // Inputs const N = 4; const X = 2; const S = [ '1' , '1' , '0' , '0' ];
// Function call minOperations(N, X, S); |
2
Time Complexity: O(N2)
Auxiliary Space: O(N), As boolean Array of length N is used.