Maximum count of 0s between two 1s in the given range for Q queries


A binary string is a string that only contains the zeroes and ones as the different characters in them. We are given a binary string and an array of a given length that will contain the pairs. Each pair defines the range, and in that range, we have to return the maximum number of zeros lying between two ones. We will implement two approaches one is the naive approach and another is the efficient approach.

Let’s understand with the help of example

Input

String str = ‘1011010110’

Array Q[][] = {{0,2}, {2,5}, {0,9}}

Output: 1 1 3

Explanation − For the range 0 to 2, we have only 1 zero between the one present at the 0th and 2nd index. For the range of 2 to 5, again we have only 1 zero present between the one present at the 2nd and 5th index or the 3rd and 5th index.

For the last query, we have three zeros present between the 0th index and both the 7th and 8th index.

Naive Approach

In this approach, we will travel for each query and will manage the count of zeros from the first one tackled in the range to the last one. If any of the side ones does not occur then in that case answer is zero.

We will traverse the string for each query and will check in the given range for the number of zeroes.

We will use a flag to mark if there is at least one present in range and if one is present then will mark the flag and start counting the zeroes from there, and if it again any character 1 appears we will store the number of zeros in the flag variable as it will always be maximum in that range.

Also, to mark the number of zeroes we will maintain a variable.

Let us see the code −

Example

#include <bits/stdc++.h>
using namespace std;
// function to find the zeroes in the range 
int zeroesInRange(int l, int r, string str){    
   // checking for the current range 
   int flag = -1; // flag to indicate the whether one is present on first side or not  
   int count = 0;
   for(int i = l; i <= r; i++){
      if(str[i] == '1'){
         if(flag == -1){
            flag = 0;
            count = 0;
         }
         else{
            flag = count;
         }
      }
      else{
         count++;
      }
   }    
   if(flag == -1){
      return 0;
   }
   else{
      return flag;
   }
}
int main(){
   string str = "1010110110";
   int Q[][2] = {{0,2}, {2,5}, {0,9}};
   int m = 3; // size of the queries     
   // traversing over the array 
   for(int i=0; i<m; i++){
      // calling the function 
      cout<<zeroesInRange(Q[i][0], Q[i][1], str)<<" ";
   }
   cout<<endl;    
   return 0;
}

Output

1 1 3 

Time and Space Complexity

The time complexity of the above code is O(Q*N) where Q is the size of the query array and N is the size of the string.

The space complexity of the above code O(1), as we are not using any extra space here.

Efficient Approach

In the previous approach, we were traversing over the array for each query making the time complexity non-linear. We will use the concept of the pre-fix array and will store the results initially to get the answer in O(1) instead of O(N) for each query.

We will store the index of the ones present to the left and right of the current index and prefix sum of the number of zeros.

For the current range we will find the right one of the left range element and rightmost one of the right range element and for them we will find the number of zeroes lying in between of them. Let us see the code −

Example

#include <bits/stdc++.h>
using namespace std;
// function to solve the queries 
void findQueries(int Q[][2], string str, int m){
   int n = str.length(); // getting the length of the string     
   // defining the vectors to store the find the one present 
   // nearest on the both left and the right side 
   // also, to store the prefix zeroes 
   vector<int> leftOne(n), rightOne(n), preZero(n);    
   int lastOne = -1; // variable to store the last one     
   // traversing over the array to get the left One 
   for(int i=0; i<n; i++){
      if(str[i] == '1'){
         lastOne = i;   
      }
      leftOne[i] = lastOne;
   }    
   lastOne = n;
   // traversing over the array to get the right One 
   for(int i=n-1; i>=0 ;i--){
      if(str[i] == '1'){
         lastOne = i;   
      }
      rightOne[i] = lastOne;
   }    
   // traversing over the array to get the prefix value of zeros 
   for(int i=0; i<n; i++){
      if(str[i] == '0'){
         preZero[i]++;
      }
      if(i != 0){
         preZero[i] += preZero[i-1];
      }
   }    
   // traversing over the queries array 
   for(int i=0; i<m; i++){
      int l = rightOne[Q[i][0]];
      int r = leftOne[Q[i][1]];        
      if(l >= r){
         cout<<0<<" ";
      }
      else{
         if(l == 0){
            cout<<preZero[r]<<" ";
         }
         else{
            cout<<preZero[r]-preZero[l]<<" ";
         }
      }
   }
   cout<<endl;
}
int main(){
   string str = "1010110110";
   int Q[][2] = {{0,2}, {2,5}, {0,9}};
   int m = 3; // size of the queries 
   // calling to the function 
   findQueries(Q, str, m);    
   return 0;
}

Output

1 1 3 

Time and Space Complexity

The time complexity of the above code is O(max(Q,N)), where Q is the number of queries and N is the length of the string.

The space complexity of the above code is O(N) because we are storing the elements in the vector.

Conclusion

In this tutorial, we have implemented a code to find the solution to queries to find the number of zeros present in between two ones of the given binary string. We have implemented two codes one is with the time complexity of O(N*Q) with constant space and another with the O(N) time complexity and O(N) space complexity.

Updated on: 17-May-2023

91 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements