Open In App

Maximum count of 0s between two 1s in given range for Q queries | Set – 2

Last Updated : 21 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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:

  1. 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”. 
  2. 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.


Javascript




// JavaScript implementation of the approach
 
// Function to get the number of 0s between two 1s
function zBetweeno(s, queries) {
 
  // Store location of 1s
  const ones = new Set();
 
  // Store number of candles before i
  const one = Array(s.length).fill(0);
 
  // Store result
  const res = [];
 
  // Storing number of candles before
  // a specific position and locations of candles in a set
  for (let i = 0; i < s.length; i++) {
    if (s[i] === '1') {
      ones.add(i);
      one[i] += 1;
    }
 
    if (i !== 0) {
      one[i] += one[i - 1];
    }
  }
 
  // Iterating over queries
  for (let query of queries) {
 
    // Get the location of first 1
    const ss = Array.from(ones).sort((a, b) => a - b).findIndex(x => x >= query[0]);
 
    // Get the location of last 1
    let ee = 0;
    if (s[query[1]] === '1') {
      ee = query[1];
    } else {
      ee = Array.from(ones).sort((a, b) => a - b).findIndex(x => x > query[1]);
    }
 
    // Check for corner cases
    if (ss > query[1] || ee < query[0]) {
      res.push(0);
      continue;
    }
 
    const tot = one[ee] - one[ss];
    const loc = ee - ss;
 
    // Storing result of the query
    res.push(loc - tot);
  }
 
  return res;
}
const queries = [[0, 4], [0, 5]];
  const input = "1001010";
 
  const res = zBetweeno(input, queries);
 
  console.log(res.join(" "));
 //This code is contributed by Edula Vinay Kumar Reddy


C#




// C# equivalent of the above code
using System;
using System.Collections.Generic;
 
// C# program for the above approach
class GFG
{
    // Function to get the number of
    // 0s between two 1s
    public static List<int> zBetweeno(string s, List<List<int>> queries)
    {
        // Store location of 1s
        SortedSet<int> ones = new SortedSet<int>();
 
        // Store number of candles before i
        int[] one = new int[s.Length];
 
        // Store result
        List<int> res = new List<int>();
 
        // 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[i] == '1')
            {
                ones.Add(i);
                one[i]++;
            }
            if (i != 0)
            {
                one[i] += one[i - 1];
            }
        }
 
        // Iterating over queries
        for (int i = 0; i < queries.Count; i++)
        {
            List<int> query = queries[i];
 
            // Get the location of first 1
            int ss = ones.GetViewBetween(query[0], int.MaxValue).Min;
 
            // Get the location of last 1
            int ee = (s[query[1]] == '1') ? query[1] : ones.GetViewBetween(0, query[1] - 1).Max;
 
            // Check for corner cases
            if (ss > query[1] || ee < query[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)
    {
        List<List<int>> queries = new List<List<int>>()
        {
            new List<int> { 0, 4 },
            new List<int> { 0, 5 }
        };
 
        string input = "1001010";
 
        List<int> res = zBetweeno(input, queries);
 
        foreach (int i in res)
            Console.Write(i + " ");
    }
}


Output

2 3 

 

Time Complexity: O(N*logN)
Auxiliary Space: O(N)

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads