Maximum count of 0s between two 1s in given range for Q queries | Set – 2
Given a binary string S of size N, and a 2D array Q[][] of queries consisting of M pairs of the form {L, R}, the task for each query is to find the maximum number of 0s lying between two 1s in the range [L, R].
Examples:
Input: S = “1001010”, Q[][] = {{0, 4}, {0, 5}}
Output: 2 3
Explanation:
The Queries are performed as per the following:
- Query(0, 4): Print 2 as there are maximum 2 0’s lying between the indices 0 and 3 in the substring over the range [0, 4] i.e., “10010”.
- Query(0, 5): Print 3 as there are maximum 3 0’s lying between the indices 0 and 5 in the substring over the range [0, 5] i.e., “100101”.
Input: S = “101”, Q[][] = {{0, 2}}
Output: 1
Approach: Another variation is already discussed in Set1 of this problem. Keep track of two entities: location of 1’s and the Number of 1’s that appeared before any specific position. Use a set to store the location of 1’s and an array to store the answer. Now to find the answer in range [i,j] use the following observation:
Let first and last 1s between given range is located at (i+first) and (i+last), then
Total 0’s between 1’s = total elements between these two locations – total 1’s between these to locations
= location difference between 1’s – (1’s appeared before (i+last) – 1’s appeared before (i+first) )
Below is the implementation of the above approach:
C++
// C++ implementation of the above approach #include <bits/stdc++.h> using namespace std; // Function to get the number of // 0s between two 1s vector< int > zBetweeno(string s, vector<vector< int > >& queries) { // Store location of 1s set< int > ones; // Store number of candles before i vector< int > one(s.size(), 0); // Store result vector< int > res; // Storing number of candles before // a specific position // and locations of candles in a set for ( int i = 0; i < s.size(); i++) { if (s[i] == '1' ) { ones.insert(i); one[i]++; } if (i != 0) one[i] += one[i - 1]; } // Iterating over queries for ( auto && query : queries) { // Get the location of first 1 int ss = *ones.lower_bound(query[0]); // Get the location of last 1 int ee = s[query[1]] == '1' ? query[1] : *--ones.lower_bound(query[1]); // Check for corner cases if (ss > query[1] || ee < query[0]) { res.push_back(0); continue ; } int tot = one[ee] - one[ss]; int loc = ee - ss; // Storing result of the query res.push_back(loc - tot); } return res; } // Driver code int main() { vector<vector< int > > queries = { { 0, 4 }, { 0, 5 } }; string input = "1001010" ; vector< int > res = zBetweeno(input, queries); for ( auto elem : res) cout << elem << " " ; cout << endl; } |
Java
import java.util.*; import java.io.*; // Java program for the above approach class GFG{ // Function to get the number of // 0s between two 1s public static ArrayList<Integer> zBetweeno(String s, ArrayList<ArrayList<Integer>> queries) { // Store location of 1s TreeSet<Integer> ones = new TreeSet<Integer>(); // Store number of candles before i int one[] = new int [s.length()]; // Store result ArrayList<Integer> res = new ArrayList<Integer>(); // Storing number of candles before // a specific position // and locations of candles in a set for ( int i = 0 ; i < s.length() ; i++) { if (s.charAt(i) == '1' ) { ones.add(i); one[i]++; } if (i != 0 ){ one[i] += one[i - 1 ]; } } // Iterating over queries for ( int i = 0 ; i < queries.size() ; i++) { ArrayList<Integer> query = queries.get(i); // Get the location of first 1 int ss = ones.ceiling(query.get( 0 )); // Get the location of last 1 int ee = s.charAt(query.get( 1 )) == '1' ? query.get( 1 ) : ones.floor(query.get( 1 )- 1 ); // Check for corner cases if (ss > query.get( 1 ) || ee < query.get( 0 )) { res.add( 0 ); continue ; } int tot = one[ee] - one[ss]; int loc = ee - ss; // Storing result of the query res.add(loc - tot); } return res; } // Driver code public static void main(String args[]) { ArrayList<ArrayList<Integer> > queries = new ArrayList<>( List.of( new ArrayList<Integer>( List.of( 0 , 4 ) ), new ArrayList<Integer>( List.of( 0 , 5 ) ) ) ); String input = "1001010" ; ArrayList<Integer> res = zBetweeno(input, queries); for ( int i = 0 ; i < res.size() ; i++){ System.out.print(res.get(i) + " " ); } System.out.println( "" ); } } // This code is contributed by subhamgoyal2014. |
Python3
# Python 3 implementation of the above approach from bisect import bisect_left # Function to get the number of # 0s between two 1s def zBetweeno(s, queries): # Store location of 1s ones = set ([]) # Store number of candles before i one = [ 0 ] * len (s) # Store result res = [] # Storing number of candles before # a specific position # and locations of candles in a set for i in range ( len (s)): if (s[i] = = '1' ): ones.add(i) one[i] + = 1 if (i ! = 0 ): one[i] + = one[i - 1 ] # Iterating over queries for query in queries: # Get the location of first 1 ss = bisect_left( list (ones), query[ 0 ]) # Get the location of last 1 if s[query[ 1 ]] = = '1' : ee = query[ 1 ] else : ee = bisect_left( list (ones), query[ 1 ]) # Check for corner cases if (ss > query[ 1 ] or ee < query[ 0 ]): res.append( 0 ) continue tot = one[ee] - one[ss] loc = ee - ss # Storing result of the query res.append(loc - tot) return res # Driver code if __name__ = = "__main__" : queries = [[ 0 , 4 ], [ 0 , 5 ]] input = "1001010" res = zBetweeno( input , queries) for elem in res: print (elem, end = " " ) # This code is contributed by ukasp. |
2 3
Time Complexity: O(N*logN)
Auxiliary Space: O(N)