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:
- A segment tree can be used to get the minimum and maximum in a range.
- 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.
- 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.
// 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 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 |
# 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# 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 |
<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> |
Yes No No
Time Complexity: O(Q*log(n))