Binary Array Range Queries to find the minimum distance between two Zeros

Prerequisite: Segment Trees

Given a binary array arr[] consisting of only 0’s and 1’s and a 2D array Q[][] consisting of K queries, the task is to find the minimum distance between two 0’s in the range [L, R] of the array for every query {L, R}.

Examples:

Input: arr[] = {1, 0, 0, 1}, Q[][] = {{0, 2}}
Output: 1
Explanation:
Clearly, in the range [0, 2], the first 0 lies at index 1 and last at index 2.
Minimum distance = 2 – 1 = 1.

Input: arr[] = {1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0}, Q[][] = {{3, 9}, {10, 13}}
Output: 2 3
Explanation:
In the range [3, 9], the minimum distance between 0’s is 2 (Index 4 and 6).
In the range [10, 13], the minimum distance between 0’s is 3 (Index 10 and 13).



Approach: The idea is to use a segment tree to solve this problem:

  1. Every node in the segment tree will have the index of leftmost 0 as well as rightmost 0 and an integer containing the minimum distance between 0’s in the subarray {L, R}.
  2. Let min be the minimum distance between two zeroes. Then, the value of min can be found after forming the segment tree as:
    min = minimum(value of min in the left node, the value of min in the right node, and the difference between the leftmost index of 0 in right node and rightmost index of 0 in left node).
  3. After computing and storing the minimum distance for every node, all the queries can be answered in logarithmic time.
    1. Below is the implementation of the above approach:

      filter_none

      edit
      close

      play_arrow

      link
      brightness_4
      code

      // C++ program to find the minimum
      // distance between two elements
      // with value 0 within a subarray (l, r)
        
      #include <bits/stdc++.h>
      using namespace std;
        
      // Structure for each node
      // in the segment tree
      struct node {
          int l0, r0;
          int min0;
      } seg[100001];
        
      // A utility function for
      // merging two nodes
      node task(node l, node r)
      {
          node x;
        
          x.l0 = (l.l0 != -1) ? l.l0 : r.l0;
        
          x.r0 = (r.r0 != -1) ? r.r0 : l.r0;
        
          x.min0 = min(l.min0, r.min0);
        
          // If both the nodes are valid
          if (l.r0 != -1 && r.l0 != -1)
        
              // Computing the minimum distance to store
              // in the segment tree
              x.min0 = min(x.min0, r.l0 - l.r0);
        
          return x;
      }
        
      // A recursive function that constructs
      // Segment Tree for given string
      void build(int qs, int qe, int ind, int arr[])
      {
          // If start is equal to end then
          // insert the array element
          if (qs == qe) {
        
              if (arr[qs] == 0) {
                  seg[ind].l0 = seg[ind].r0 = qs;
                  seg[ind].min0 = INT_MAX;
              }
        
              else {
                  seg[ind].l0 = seg[ind].r0 = -1;
                  seg[ind].min0 = INT_MAX;
              }
        
              return;
          }
        
          int mid = (qs + qe) >> 1;
        
          // Build the segment tree
          // for range qs to mid
          build(qs, mid, ind << 1, arr);
        
          // Build the segment tree
          // for range mid+1 to qe
          build(mid + 1, qe, ind << 1 | 1, arr);
        
          // Merge the two child nodes
          // to obtain the parent node
          seg[ind] = task(seg[ind << 1],
                          seg[ind << 1 | 1]);
      }
        
      // Query in a range qs to qe
      node query(int qs, int qe, int ns, int ne, int ind)
      {
          node x;
          x.l0 = x.r0 = -1;
          x.min0 = INT_MAX;
        
          // If the range lies in this segment
          if (qs <= ns && qe >= ne)
              return seg[ind];
        
          // If the range is out of the bounds
          // of this segment
          if (ne < qs || ns > qe || ns > ne)
              return x;
        
          // Else query for the right and left
          // child node of this subtree
          // and merge them
          int mid = (ns + ne) >> 1;
        
          node l = query(qs, qe, ns, mid, ind << 1);
          node r = query(qs, qe, mid + 1, ne, ind << 1 | 1);
        
          x = task(l, r);
          return x;
      }
        
      // Driver code
      int main()
      {
        
          int arr[] = { 1, 1, 0, 1, 0, 1,
                        0, 1, 0, 1, 0, 1, 1, 0 };
        
          int n = sizeof(arr) / sizeof(arr[0]);
        
          // Build the segment tree
          build(0, n - 1, 1, arr);
        
          // Queries
          int Q[][2] = { { 3, 9 }, { 10, 13 } };
        
          for (int i = 0; i < 2; i++) {
        
      // Finding the answer for every query
      // and printing it
              node ans = query(Q[i][0], Q[i][1],
                               0, n - 1, 1);
        
              cout << ans.min0 << endl;
          }
        
          return 0;
      }
      chevron_right
      
      
      Output:
      2
      3
      





      Check out this Author's contributed articles.

      If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

      Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.


Article Tags :
Practice Tags :