Skip to content
Related Articles

Related Articles

Improve Article
Query to check if a range is made up of consecutive elements
  • Difficulty Level : Medium
  • Last Updated : 11 Jun, 2021

Given an array of n non-consecutive integers and Q queries, the task is to check whether for the given range l and r, the elements are consecutive or not.
Examples: 
 

Input: arr = { 2, 4, 3, 7, 6, 1}, Q = { (1, 3), (3, 5), (5, 6) } 
Output: Yes, No, No 
Explanation: Array elements from (1, 3) = {2, 4, 3}, (3, 5) = {3, 7, 6}, (5, 6) = {6, 1} 
So the answer is Yes, No, No 
Input: arr = {1, 2, 3, 4, 5}, Q = { (1, 2), (4, 5), (1, 5) } 
Output:Yes, Yes, Yes 
 

 

Naive Approach: 
The sub array between range l and r can be sorted and checked if it contains consecutive elements or not.
Time Complexity: O(q*n*log n) 
where n is the size of the array and q is the number of queries.
Efficient approach: 
 

  1. A segment tree can be used to get the minimum and maximum in a range.
  2. If the minimum element of a sub array is x and the maximum element is y then we can there is no element less than x and more than y, so we can say that x<=arr[i]<=y.
  3. As there are no repeated elements, so it can be concluded that if the difference of maximum and minimum element + 1 is equal to the length of the range (r-l+1) then the range consists of consecutive elements.

Below is the implementation of the above approach. 
 



CPP




// C++ implementation of the above approach.
#include <bits/stdc++.h>
using namespace std;
 
// Segment tree
int tree_min[1000001],
    tree_max[1000001];
 
// Functions to return
// minimum and maximum
int min(int a, int b)
{
    return a < b ? a : b;
}
 
int max(int a, int b)
{
    return a > b ? a : b;
}
 
// Segment tree for minimum element
void build_min(int array[], int node,
               int left, int right)
{
    // If left is equal to right
    if (left == right)
        tree_min[node] = array[left];
 
    else {
        // Divide the segment into equal halves
        build_min(array, 2 * node, left,
                  (left + right) / 2);
 
        build_min(array, 2 * node + 1,
                  (left + right) / 2 + 1, right);
 
        // Update the element as minimum
        // of the divided two subarrays
        tree_min[node] = min(tree_min[2 * node],
                             tree_min[2 * node + 1]);
    }
}
 
// Query to find a minimum
// in a given ranges
int query_min(int node, int c_l,
              int c_r, int l, int r)
{
    // Out of range
    if (c_l > r || c_r < l)
        return 1e9;
 
    // Within the range completely
    if (c_l >= l && c_r <= r)
        return tree_min[node];
    else
        // Divide the range into two halves
        // Query for each half
        // and return the minimum of two
        return min(query_min(2 * node, c_l,
                             (c_l + c_r) / 2, l, r),
                   query_min(2 * node + 1,
                             (c_l + c_r) / 2 + 1,
                             c_r, l, r));
}
 
// Segment tree for maximum element
void build_max(int array[], int node,
               int left, int right)
{
    // If left is equal to right
    if (left == right)
        tree_max[node] = array[left];
 
    else {
        // Divide the segment into equal halves
        build_max(array, 2 * node, left,
                  (left + right) / 2);
 
        build_max(array, 2 * node + 1,
                  (left + right) / 2 + 1, right);
 
        // Update the element as maximum
        // of the divided two subarrays
        tree_max[node] = max(tree_max[2 * node],
                             tree_max[2 * node + 1]);
    }
}
 
// Query to find maximum
// in a given ranges
int query_max(int node, int c_l,
              int c_r, int l, int r)
{
    // Out of range
    if (c_l > r || c_r < l)
        return -1;
 
    // Within the range completely
    if (c_l >= l && c_r <= r)
        return tree_max[node];
    else
        // Divide the range into two halves
        // and query for each half
        // and return the maximum of two
        return max(query_max(2 * node, c_l,
                             (c_l + c_r) / 2, l, r),
                   query_max(2 * node + 1,
                             (c_l + c_r) / 2 + 1,
                             c_r, l, r));
}
 
// Build the tree
void init(int array[], int n)
{
    build_min(array, 1, 0, n - 1);
    build_max(array, 1, 0, n - 1);
}
 
// Check if the given range is Consecutive
bool isConsecutive(int x, int y, int n)
{
    return ((query_max(1, 0, n - 1, x, y)
             - query_min(1, 0, n - 1, x, y))
            == (y - x));
}
 
// Driver code
int main()
{
    int arr[] = { 2, 4, 3, 7, 6, 1 };
    int query[][2] = { { 1, 3 }, { 3, 5 }, { 5, 6 } };
    int n = sizeof(arr) / sizeof(int), q = 3;
    init(arr, n);
 
    for (int i = 0; i < q; i++) {
        int l, r;
        l = query[i][0];
        r = query[i][1];
 
        cout << (isConsecutive(l - 1, r - 1, n) ?
                           "Yes" : "No") << "\n";
    }
 
    return 0;
}

Java




// Java implementation of the above approach.
class GFG
{
 
    // Segment tree
    static int[] tree_min = new int[1000001];
    static int[] tree_max = new int[1000001];
 
    // Functions to return
    // minimum and maximum
    static int min(int a, int b)
    {
        return a < b ? a : b;
    }
 
    static int max(int a, int b)
    {
        return a > b ? a : b;
    }
 
    // Segment tree for minimum element
    static void build_min(int array[], int node, int left, int right)
    {
        // If left is equal to right
        if (left == right)
            tree_min[node] = array[left];
 
        else
        {
            // Divide the segment into equal halves
            build_min(array, 2 * node, left, (left + right) / 2);
 
            build_min(array, 2 * node + 1,
                    (left + right) / 2 + 1, right);
 
            // Update the element as minimum
            // of the divided two subarrays
            tree_min[node] = Math.min(tree_min[2 * node],
                    tree_min[2 * node + 1]);
        }
    }
 
    // Query to find a minimum
    // in a given ranges
    static int query_min(int node, int c_l, int c_r, int l, int r)
    {
        // Out of range
        if (c_l > r || c_r < l)
            return (int) 1e9;
 
        // Within the range completely
        if (c_l >= l && c_r <= r)
            return tree_min[node];
        else
            // Divide the range into two halves
            // Query for each half
            // and return the minimum of two
            return min(query_min(2 * node, c_l, (c_l + c_r) / 2, l, r),
                    query_min(2 * node + 1, (c_l + c_r) / 2 + 1, c_r, l, r));
    }
 
    // Segment tree for maximum element
    static void build_max(int array[], int node, int left, int right)
    {
        // If left is equal to right
        if (left == right)
            tree_max[node] = array[left];
 
        else
        {
            // Divide the segment into equal halves
            build_max(array, 2 * node, left, (left + right) / 2);
 
            build_max(array, 2 * node + 1, (left + right) / 2 + 1, right);
 
            // Update the element as maximum
            // of the divided two subarrays
            tree_max[node] = Math.max(tree_max[2 * node],
                    tree_max[2 * node + 1]);
        }
    }
 
    // Query to find maximum
    // in a given ranges
    static int query_max(int node, int c_l, int c_r, int l, int r)
    {
        // Out of range
        if (c_l > r || c_r < l)
            return -1;
 
        // Within the range completely
        if (c_l >= l && c_r <= r)
            return tree_max[node];
        else
            // Divide the range into two halves
            // and query for each half
            // and return the maximum of two
            return Math.max(query_max(2 * node, c_l, (c_l + c_r) / 2, l, r),
                    query_max(2 * node + 1, (c_l + c_r) / 2 + 1, c_r, l, r));
    }
 
    // Build the tree
    static void init(int array[], int n)
    {
        build_min(array, 1, 0, n - 1);
        build_max(array, 1, 0, n - 1);
    }
 
    // Check if the given range is Consecutive
    static boolean isConsecutive(int x, int y, int n)
    {
        return ((query_max(1, 0, n - 1, x, y) -
                query_min(1, 0, n - 1, x, y)) == (y - x));
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int arr[] = { 2, 4, 3, 7, 6, 1 };
        int query[][] = { { 1, 3 }, { 3, 5 }, { 5, 6 } };
        int n = arr.length, q = 3;
        init(arr, n);
 
        for (int i = 0; i < q; i++)
        {
            int l, r;
            l = query[i][0];
            r = query[i][1];
 
            System.out.print((isConsecutive(l - 1, r - 1, n) ?
                    "Yes" : "No") + "\n");
        }
    }
}
 
// This code is contributed by PrinciRaj1992

Python




# Python3 implementation of the above approach.
 
# Segment tree
tree_min = [0] * 1000001
 
tree_max = [0] * 1000001
 
# Segment tree for minimum element
def build_min(array, node,left, right):
 
    # If left is equal to right
    if (left == right):
        tree_min[node] = array[left]
 
    else :
        # Divide the segment into equal halves
        build_min(array, 2 * node, left,(left + right) // 2)
 
        build_min(array, 2 * node + 1,(left + right) // 2 + 1, right)
 
        # Update the element as minimum
        # of the divided two subarrays
        tree_min[node] = min(tree_min[2 * node], tree_min[2 * node + 1])
 
# Query to find a minimum
# in a given ranges
def query_min(node, c_l, c_r, l, r):
 
    # Out of range
    if (c_l > r or c_r < l):
        return 10**9
 
    # Within the range completely
    if (c_l >= l and c_r <= r):
        return tree_min[node]
    else:
        # Divide the range into two halves
        # Query for each half
        # and return the minimum of two
        return min(query_min(2 * node, c_l,(c_l + c_r) // 2, l, r),
                query_min(2 * node + 1, (c_l + c_r) // 2 + 1,c_r, l, r))
 
# Segment tree for maximum element
def build_max(array, node, left, right):
 
    # If left is equal to right
    if (left == right):
        tree_max[node] = array[left]
 
    else :
        # Divide the segment into equal halves
        build_max(array, 2 * node, left,(left + right) // 2)
 
        build_max(array, 2 * node + 1,(left + right) // 2 + 1, right)
 
        # Update the element as maximum
        # of the divided two subarrays
        tree_max[node] = max(tree_max[2 * node],tree_max[2 * node + 1])
 
# Query to find maximum
# in a given ranges
def query_max(node, c_l, c_r, l, r):
 
    # Out of range
    if (c_l > r or c_r < l):
        return -1
 
    # Within the range completely
    if (c_l >= l and c_r <= r):
        return tree_max[node]
    else:
        # Divide the range into two halves
        # and query for each half
        # and return the maximum of two
        return max(query_max(2 * node, c_l,(c_l + c_r) // 2, l, r),query_max(2 * node + 1,(c_l + c_r) // 2 + 1,c_r, l, r))
 
# Build the tree
def init(array, n):
 
    build_min(array, 1, 0, n - 1)
    build_max(array, 1, 0, n - 1)
 
# Check if the given range is Consecutive
def isConsecutive(x, y, n):
 
    return ((query_max(1, 0, n - 1, x, y) - query_min(1, 0, n - 1, x, y)) == (y - x))
 
# Driver code
 
arr = [2, 4, 3, 7, 6, 1]
query = [ [1, 3] , [3, 5 ], [5, 6] ]
n = len(arr)
q = 3
init(arr, n)
 
for i in range(q):
    l = query[i][0]
    r = query[i][1]
 
    if (isConsecutive(l - 1, r - 1, n) ):
        print("Yes")
    else:
        print("No")
 
# This code is contributed by mohit kumar 29

C#




// C# implementation of the above approach.
using System;
 
class GFG
{
 
    // Segment tree
    static int[] tree_min = new int[1000001];
    static int[] tree_max = new int[1000001];
 
    // Functions to return
    // minimum and maximum
    static int min(int a, int b)
    {
        return a < b ? a : b;
    }
 
    static int max(int a, int b)
    {
        return a > b ? a : b;
    }
 
    // Segment tree for minimum element
    static void build_min(int []array, int node,
                           int left, int right)
    {
        // If left is equal to right
        if (left == right)
            tree_min[node] = array[left];
 
        else
        {
            // Divide the segment into equal halves
            build_min(array, 2 * node, left, (left + right) / 2);
 
            build_min(array, 2 * node + 1,
                    (left + right) / 2 + 1, right);
 
            // Update the element as minimum
            // of the divided two subarrays
            tree_min[node] = Math.Min(tree_min[2 * node],
                    tree_min[2 * node + 1]);
        }
    }
 
    // Query to find a minimum
    // in a given ranges
    static int query_min(int node, int c_l,
                        int c_r, int l, int r)
    {
        // Out of range
        if (c_l > r || c_r < l)
            return (int) 1e9;
 
        // Within the range completely
        if (c_l >= l && c_r <= r)
            return tree_min[node];
        else
            // Divide the range into two halves
            // Query for each half
            // and return the minimum of two
            return min(query_min(2 * node, c_l,
                        (c_l + c_r) / 2, l, r),
                        query_min(2 * node + 1,
                        (c_l + c_r) / 2 + 1, c_r, l, r));
    }
 
    // Segment tree for maximum element
    static void build_max(int []array, int node,
                           int left, int right)
    {
        // If left is equal to right
        if (left == right)
            tree_max[node] = array[left];
 
        else
        {
            // Divide the segment into equal halves
            build_max(array, 2 * node, left, (left + right) / 2);
 
            build_max(array, 2 * node + 1, (left + right) / 2 + 1, right);
 
            // Update the element as maximum
            // of the divided two subarrays
            tree_max[node] = Math.Max(tree_max[2 * node],
                    tree_max[2 * node + 1]);
        }
    }
 
    // Query to find maximum
    // in a given ranges
    static int query_max(int node, int c_l,
                        int c_r, int l, int r)
    {
        // Out of range
        if (c_l > r || c_r < l)
            return -1;
 
        // Within the range completely
        if (c_l >= l && c_r <= r)
            return tree_max[node];
        else
            // Divide the range into two halves
            // and query for each half
            // and return the maximum of two
            return Math.Max(query_max(2 * node, c_l,
                            (c_l + c_r) / 2, l, r),
                            query_max(2 * node + 1,
                            (c_l + c_r) / 2 + 1, c_r, l, r));
    }
 
    // Build the tree
    static void init(int []array, int n)
    {
        build_min(array, 1, 0, n - 1);
        build_max(array, 1, 0, n - 1);
    }
 
    // Check if the given range is Consecutive
    static bool isConsecutive(int x, int y, int n)
    {
        return ((query_max(1, 0, n - 1, x, y) -
                query_min(1, 0, n - 1, x, y)) == (y - x));
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        int []arr = {2, 4, 3, 7, 6, 1};
        int [,]query = {{ 1, 3 }, { 3, 5 }, { 5, 6 }};
        int n = arr.Length, q = 3;
        init(arr, n);
 
        for (int i = 0; i < q; i++)
        {
            int l, r;
            l = query[i,0];
            r = query[i,1];
 
            Console.Write((isConsecutive(l - 1, r - 1, n) ?
                    "Yes" : "No") + "\n");
        }
    }
}
 
// This code is contributed by Rajput-Ji

Javascript




<script>
 
// JavaScript implementation of the above approach.
 
// Segment tree
let  tree_min = new Array(1000001);
let tree_max = new Array(1000001);
 
// Functions to return
// minimum and maximum
function min(a,b)
{
    return a < b ? a : b;
}
 
function max(a,b)
{
    return a > b ? a : b;
}
 
// Segment tree for minimum element
function build_min(array,node,left,right)
{
    // If left is equal to right
        if (left == right)
            tree_min[node] = array[left];
   
        else
        {
            // Divide the segment into equal halves
            build_min(array, 2 * node, left,
            Math.floor((left + right) / 2));
   
            build_min(array, 2 * node + 1,
                    Math.floor((left + right) / 2) + 1, right);
   
            // Update the element as minimum
            // of the divided two subarrays
            tree_min[node] = Math.min(tree_min[2 * node],
                    tree_min[2 * node + 1]);
        }
}
 
// Query to find a minimum
// in a given ranges
function query_min(node,c_l,c_r,l,r)
{
    // Out of range
        if (c_l > r || c_r < l)
            return 1e9;
   
        // Within the range completely
        if (c_l >= l && c_r <= r)
            return tree_min[node];
        else
            // Divide the range into two halves
            // Query for each half
            // and return the minimum of two
            return min(query_min(2 * node, c_l,
            Math.floor((c_l + c_r) / 2), l, r),
            query_min(2 * node + 1,
            Math.floor((c_l + c_r) / 2) + 1, c_r, l, r));
}
 
// Segment tree for maximum element
function build_max(array,node,left,right)
{
    // If left is equal to right
        if (left == right)
            tree_max[node] = array[left];
   
        else
        {
            // Divide the segment into equal halves
            build_max(array, 2 * node, left,
            Math.floor((left + right) / 2));
   
            build_max(array, 2 * node + 1,
            Math.floor((left + right) / 2) + 1, right);
   
            // Update the element as maximum
            // of the divided two subarrays
            tree_max[node] = Math.max(tree_max[2 * node],
                    tree_max[2 * node + 1]);
        }
}
 
 // Query to find maximum
 // in a given ranges
function query_max(node,c_l,c_r,l,r)
{
    // Out of range
        if (c_l > r || c_r < l)
            return -1;
   
        // Within the range completely
        if (c_l >= l && c_r <= r)
            return tree_max[node];
        else
            // Divide the range into two halves
            // and query for each half
            // and return the maximum of two
            return Math.max(query_max(2 * node, c_l,
            Math.floor((c_l + c_r) / 2), l, r),
            query_max(2 * node + 1,
            Math.floor((c_l + c_r) / 2) + 1, c_r, l, r));
}
 
// Build the tree
function init(array,n)
{
    build_min(array, 1, 0, n - 1);
        build_max(array, 1, 0, n - 1);
}
 
// Check if the given range is Consecutive
function isConsecutive(x,y,n)
{
    return ((query_max(1, 0, n - 1, x, y) -
                query_min(1, 0, n - 1, x, y)) == (y - x));
}
 
// Driver code
let arr=[ 2, 4, 3, 7, 6, 1];
let query=[[ 1, 3 ], [ 3, 5 ], [ 5, 6 ] ];
let n = arr.length, q = 3;
init(arr, n);
for (let i = 0; i < q; i++)
        {
            let l, r;
            l = query[i][0];
            r = query[i][1];
   
            document.write((isConsecutive(l - 1, r - 1, n) ?
                    "Yes" : "No") + "<br>");
        }
 
 
 
// This code is contributed by patel2127
 
</script>
Output: 
Yes
No
No

 

Time Complexity: O(Q*log(n))
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live 




My Personal Notes arrow_drop_up
Recommended Articles
Page :