Min-Max Range Queries in Array in C++

C++Server Side ProgrammingProgramming

Given an array Arr[] containing N elements. The goal is to find the minimum and maximum value from indexes of query.

According to the query we are given starting index and ending indexes.

For Example

In − Arr[] = { 1, 2, 3, 4, 5 } QStart = 1 QEnd = 4

Out 

Minimum Value : 2

Maximum Value : 5

Explanation −In the above queries the starting index is 1 and ending index is 4. Between these two indexes, minimum value in Arr is 2 and maximum value is 5

In − Arr[] = { 10, 12, 3, 2, 5, 18 } QStart = 2 QEnd = 5

Out 

Minimum Value : 2

Maximum Value : 18

Explanation − In the above queries the starting index is 2 and ending index is 5. Between these two indexes, minimum value in Arr is 2 and maximum value is 18

Approach used in the below program is as follows −

In this approach we will use segment trees for the range lpos to rpos to find the minimum and maximum values in the given query range.

  • Take the input array Arr[] and query indexes QStart and QEnd.

  • Take the result of type value.

  • Structure value is used to store minimum and maximum value found in an array using a given query.

  • Structure value is used to store minimum and maximum value found in an array using a given query.

  • Function minMax(struct value *root1, int num, int qStart1, int qEnd1) takes query indexes and finds minimum and maximum in an array between index range qStart1 and qEnd1.

  • Check if ( qStart1 < 0 OR qEnd1 > num-1 OR qStart1 > qEnd1 ). If true then input range in the query is invalid.

  • Otherwise, call minmaxFind(root1, 0, num-1, qStart1, qEnd1, 0).

  • Function minmaxFind(struct value *root, int startT, int endT, int qStart, int qEnd, int pos) is a recursive function. It takes a pointer to segment tree- root, starting and ending index of current value as startT and endT.

  • It also takes a starting and ending index in query range. The current index of value in the segment tree has index pos.

  • If (qStart <= startT) AND if( qEnd >= endT) then the segment of current value is part of the given range. So return minimum and maximum in that value.

  • If it is outside the range then update the current value with minVal and maxVal.

  • If current part overlaps with given range then :-

  • Take middl = startT + ( endT - startT )/2.

  • Take p1 and p2 as 2*pos+1 and =2*pos+2.

  • Update lpos as lpos = minmaxFind(root, startT, middl, qStart, qEnd, p1) and rpos as minmaxFind(root, middl+1, endT, qStart, qEnd, p2).

  • Set temp.minVal as minimum of lpos.minVal and rpos.minVal.

  • Set temp.maxVal as maximum of lpos.maxVal and rpos.maxVal.

  • Return temp.

  • Function segmentTree(int arr2[], int startT2, int endT2, struct value *root2, int pos2) is used to construct a segment tree for array arr2[] with index range as startT2 and endT2 and current value position is pos2.

  • Function *createTree(int arr0[], int num0) is used to construct a segment tree from a given array arr0. This function allocates memory for segment trees and calls segmentTree() for memory allocation.

Example

#include<bits/stdc++.h>
using namespace std;
struct value{
   int minVal;
   int maxVal;
};
struct value minmaxFind(struct value *root, int startT, int endT, int qStart,
   int qEnd, int pos){
   struct value temp, lpos ,rpos;
   if (qStart <= startT) {
      if( qEnd >= endT)
         { return root[pos]; }
   }
   if (endT < qStart || startT > qEnd) {
      temp.minVal = 9999;
      temp.maxVal = -9999;
      return temp;
   }
   int middl = startT + ( endT - startT )/2;
   int p1=2*pos+1;
   int p2=2*pos+2;
   lpos = minmaxFind(root, startT, middl, qStart, qEnd, p1);
   rpos = minmaxFind(root, middl+1, endT, qStart, qEnd, p2);
   temp.minVal = (lpos.minVal<rpos.minVal) ? lpos.minVal : rpos.minVal ;
   temp.maxVal = (lpos.maxVal>rpos.maxVal) ? lpos.maxVal : rpos.maxVal ;
   return temp;
}
struct value minMax(struct value *root1, int num, int qStart1, int qEnd1){
   struct value temp1;
   if (qStart1 < 0 || qEnd1 > num-1 || qStart1 > qEnd1){
      cout<<"Please enter Valid input!!";
      temp1.minVal = 9999;
      temp1.maxVal = -9999;
      return temp1;
   }
   return minmaxFind(root1, 0, num-1, qStart1, qEnd1, 0);
}
void segmentTree(int arr2[], int startT2, int endT2, struct value *root2, int pos2){ 
   if (startT2 == endT2) { 
      root2[pos2].minVal = arr2[startT2];
      root2[pos2].maxVal = arr2[startT2];
      return ;
   }
   int p1=pos2*2+1;   
   int p2=pos2*2+2;
   int middl2 = startT2+(endT2-startT2)/2;
   segmentTree(arr2, startT2, middl2, root2, p1);
   segmentTree(arr2, middl2+1, endT2, root2, p2);
   root2[pos2].minVal = root2[p1].minVal<root2[p2].minVal ? root2[p1].minVal : root2[p2].minVal;
   root2[pos2].maxVal = root2[p1].maxVal>root2[p2].maxVal ? root2[p1].maxVal : root2[p2].maxVal;
}
struct value *createTree(int arr0[], int num0) { 
   int height = (int)(ceil(log2(num0)));
   int maxS = 2*(int)pow(2, height) - 1;
   struct value *root0 = new struct value[maxS];
   segmentTree(arr0, 0, num0-1, root0, 0);
   return root0;
}
int main() { 
   int Arr[] = { 1, 2, 3, 4, 5 };
   int length = sizeof(Arr)/sizeof(Arr[0]);
   struct value *tree = createTree(Arr, length);
   int QStart = 1;
   int QEnd = 4;
   struct value answer=minMax(tree, length, QStart, QEnd);
   cout<<"Minimum Value : "<<answer.minVal<<endl;
   cout<<"Maximum Value : "<<answer.maxVal;
   return 0;
}

Output

If we run the above code it will generate the following Output

Minimum Value : 2
Maximum Value : 5
raja
Published on 22-Oct-2021 09:33:42
Advertisements