Given an integer array arr[] of size N and an integer X, the task is to find the longest sub-array where the absolute difference between any two elements is not greater than X.
Examples:
Input: arr = { 8, 4, 2, 6, 7 }, X = 4
Output: 4 2 6
Explanation:
The sub-array described by index [1, 3], i.e, { 4, 2, 6 } contains no such difference of two elements which is greater than 4.Input: arr = { 15, 10, 1, 2, 4, 7, 2}, X = 5
Output: 2 4 7 2
Explanation:
The sub-array described by indexes [3, 6], i.e, { 2, 4, 7, 2 } contains no such difference of two elements which is greater than 5.
Naive Approach: Simple solution is to consider all subarrays one by one, find the maximum and minimum element of that sub-array and check if their difference is not greater than X. Among all such sub-arrays print the longest sub-array.
Time Complexity: O(N3)
Longest subarray in which absolute difference between any two element is not greater than X using Sliding Window and Map:
The idea is to use the Sliding Window Technique to consider a sub-array and use a Map data structure to find the maximum and minimum element in that sub-array.
- At first the Start and End of the window points to the 0-th index.
- At every iteration, the element at End is inserted in the Map if not already present or otherwise its count is incremented.
- If the difference between the maximum and minimum element is not greater than X, then update the maximum length of the required sub-array and store the beginning of that sub-array in a variable.
- Otherwise, increment the Start of the window until the difference between the maximum and minimum element is not greater than X.
- When incrementing the Start, the size of the window decreases, remove the element at the Start from the Map if and only if the count of that element becomes zero.
Finally, print the sub-array with the longest length, and the absolute difference between any two elements is not greater than the X.
Below is the implementation of the above approach:
// C++ program to find the longest sub-array // where the absolute difference between any // two elements is not greater than X #include <bits/stdc++.h> using namespace std;
// Function that prints the longest sub-array // where the absolute difference between any // two element is not greater than X void longestSubarray( int * A, int N, int X)
{ // Initialize a variable to store
// length of longest sub-array
int maxLen = 0;
// Initialize a variable to store the
// beginning of the longest sub-array
int beginning = 0;
// Initialize a map to store the maximum
// and the minimum elements for a given window
map< int , int > window;
// Initialize the window
int start = 0, end = 0;
// Loop through the array
for (; end < N; end++) {
// Increment the count of that
// element in the window
window[A[end]]++;
// Find the maximum and minimum element
// in the current window
auto minimum = window.begin()->first;
auto maximum = window.rbegin()->first;
// If the difference is not
// greater than X
if (maximum - minimum <= X) {
// Update the length of the longest
// sub-array and store the beginning
// of the sub-array
if (maxLen < end - start + 1) {
maxLen = end - start + 1;
beginning = start;
}
}
// Decrease the size of the window
else {
while (start < end) {
// Remove the element at start
window[A[start]]--;
// Remove the element from the window
// if its count is zero
if (window[A[start]] == 0) {
window.erase(window.find(A[start]));
}
// Increment the start of the window
start++;
// Find the maximum and minimum element
// in the current window
auto minimum = window.begin()->first;
auto maximum = window.rbegin()->first;
// Stop decreasing the size of window
// when difference is not greater
if (maximum - minimum <= X)
break ;
}
}
}
// Print the longest sub-array
for ( int i = beginning; i < beginning + maxLen; i++)
cout << A[i] << " " ;
} // Driver Code int main()
{ int arr[] = { 15, 10, 1, 2, 4, 7, 2 }, X = 5;
int n = sizeof (arr) / sizeof (arr[0]);
longestSubarray(arr, n, X);
return 0;
} |
// JAVA program to find the longest sub-array // where the absolute difference between any // two elements is not greater than X import java.io.*;
import java.lang.*;
import java.util.*;
class GFG
{ // Function that prints the longest sub-array
// where the absolute difference between any
// two element is not greater than X
static void longestSubarray( int A[], int N, int X)
{
// Initialize a variable to store
// length of longest sub-array
int maxLen = 0 ;
// Initialize a variable to store the
// beginning of the longest sub-array
int beginning = 0 ;
// Initialize a map to store the maximum
// and the minimum elements for a given window
TreeMap<Integer, Integer> window = new TreeMap<>();
// Initialize the window
int start = 0 , end = 0 ;
// Loop through the array
for (; end < N; end++)
{
// Increment the count of that
// element in the window
window.put(A[end],
window.getOrDefault(A[end], 0 ) + 1 );
// Find the maximum and minimum element
// in the current window
int minimum = window.firstKey();
int maximum = window.lastKey();
// If the difference is not
// greater than X
if (maximum - minimum <= X)
{
// Update the length of the longest
// sub-array and store the beginning
// of the sub-array
if (maxLen < end - start + 1 ) {
maxLen = end - start + 1 ;
beginning = start;
}
}
// Decrease the size of the window
else {
while (start < end)
{
// Remove the element at start
window.put(A[start],
window.get(A[start]) - 1 );
// Remove the element from the window
// if its count is zero
if (window.get(A[start]) == 0 ) {
window.remove(A[start]);
}
// Increment the start of the window
start++;
// Find the maximum and minimum element
// in the current window
minimum = window.firstKey();
maximum = window.lastKey();
// Stop decreasing the size of window
// when difference is not greater
if (maximum - minimum <= X)
break ;
}
}
}
// Print the longest sub-array
for ( int i = beginning; i < beginning + maxLen; i++)
System.out.print(A[i] + " " );
}
// Driver Code
public static void main(String[] args)
{
// Given array
int arr[] = { 15 , 10 , 1 , 2 , 4 , 7 , 2 }, X = 5 ;
// store the size of the array
int n = arr.length;
// Function call
longestSubarray(arr, n, X);
}
} // This code is contributed by Kingash. |
# Python3 program to find the longest sub-array # where the absolute difference between any # two elements is not greater than X # Function that prints the longest sub-array # where the absolute difference between any # two element is not greater than X def longestSubarray(A, N, X):
# Initialize a variable to store
# length of longest sub-array
maxLen = 0
# Initialize a variable to store the
# beginning of the longest sub-array
beginning = 0
# Initialize a map to store the maximum
# and the minimum elements for a given window
window = {}
# Initialize the window
start = 0
# Loop through the array
for end in range (N):
# Increment the count of that
# element in the window
if A[end] in window:
window[A[end]] + = 1
else :
window[A[end]] = 1
# Find the maximum and minimum element
# in the current window
minimum = min ( list (window.keys()))
maximum = max ( list (window.keys()))
# If the difference is not
# greater than X
if maximum - minimum < = X:
# Update the length of the longest
# sub-array and store the beginning
# of the sub-array
if maxLen < end - start + 1 :
maxLen = end - start + 1
beginning = start
# Decrease the size of the window
else :
while start < end:
# Remove the element at start
window[A[start]] - = 1
# Remove the element from the window
# if its count is zero
if window[A[start]] = = 0 :
window.pop(A[start])
# Increment the start of the window
start + = 1
# Find the maximum and minimum element
# in the current window
minimum = min ( list (window.keys()))
maximum = max ( list (window.keys()))
# Stop decreasing the size of window
# when difference is not greater
if maximum - minimum < = X:
break
# Print the longest sub-array
for i in range (beginning, beginning + maxLen):
print (A[i], end = ' ' )
# Driver Code arr = [ 15 , 10 , 1 , 2 , 4 , 7 , 2 ]
X = 5
n = len (arr)
longestSubarray(arr, n, X) # This code is contributed by Shivam Singh |
// C# program to find the longest sub-array // where the absolute difference between any // two elements is not greater than X using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{ // Function that prints the longest sub-array
// where the absolute difference between any
// two element is not greater than X
static void longestSubarray( int [] A, int N, int X)
{
// Initialize a variable to store
// length of longest sub-array
int maxLen = 0;
// Initialize a variable to store the
// beginning of the longest sub-array
int beginning = 0;
// Initialize a map to store the maximum
// and the minimum elements for a given window
Dictionary< int , int > window = new Dictionary< int , int >();
// Initialize the window
int start = 0, end = 0;
// Loop through the array
for (; end < N; end++)
{
// Increment the count of that
// element in the window
if (!window.ContainsKey(A[end]))
window[A[end]] = 0;
window[A[end]]++;
// Find the maximum and minimum element
// in the current window
int minimum = window.Keys.Min();
int maximum = window.Keys.Max();
// If the difference is not
// greater than X
if (maximum - minimum <= X)
{
// Update the length of the longest
// sub-array and store the beginning
// of the sub-array
if (maxLen < end - start + 1) {
maxLen = end - start + 1;
beginning = start;
}
}
// Decrease the size of the window
else {
while (start < end)
{
// Remove the element at start
window[A[start]]--;
// Remove the element from the window
// if its count is zero
if (window[A[start]] == 0) {
window.Remove(A[start]);
}
// Increment the start of the window
start++;
// Find the maximum and minimum element
// in the current window
minimum =window.Keys.Min();
maximum = window.Keys.Max();
// Stop decreasing the size of window
// when difference is not greater
if (maximum - minimum <= X)
break ;
}
}
}
// Print the longest sub-array
for ( int i = beginning; i < beginning + maxLen; i++)
Console.Write(A[i] + " " );
}
// Driver Code
public static void Main( string [] args)
{
// Given array
int [] arr = { 15, 10, 1, 2, 4, 7, 2 };
int X = 5;
// store the size of the array
int n = arr.Length;
// Function call
longestSubarray(arr, n, X);
}
} // This code is contributed by phasing17. |
<script> // JavaScript program to find the longest sub-array // where the absolute difference between any // two elements is not greater than X // Function that prints the longest sub-array // where the absolute difference between any // two element is not greater than X function longestSubarray(A, N, X){
// Initialize a variable to store
// length of longest sub-array
let maxLen = 0
// Initialize a variable to store the
// beginning of the longest sub-array
let beginning = 0
// Initialize a map to store the maximum
// and the minimum elements for a given window
let window = new Map()
// Initialize the window
let start = 0
// Loop through the array
for (let end=0;end<N;end++){
// Increment the count of that
// element in the window
if (window.has(A[end]))
window.set(A[end],window.get(A[end]) + 1)
else
window.set(A[end] , 1)
// Find the maximum and minimum element
// in the current window
let minimum = Math.min(...window.keys())
let maximum = Math.max(...window.keys())
// If the difference is not
// greater than X
if (maximum - minimum <= X){
// Update the length of the longest
// sub-array and store the beginning
// of the sub-array
if (maxLen < end - start + 1){
maxLen = end - start + 1
beginning = start
}
}
// Decrease the size of the window
else {
while (start < end){
// Remove the element at start
window.set(A[start],window.get(A[start]) - 1)
// Remove the element from the window
// if its count is zero
if (window.get(A[start]) == 0)
window. delete (A[start])
// Increment the start of the window
start += 1
// Find the maximum and minimum element
// in the current window
minimum = Math.min(...window.keys())
maximum = Math.max(...window.keys())
// Stop decreasing the size of window
// when difference is not greater
if (maximum - minimum <= X)
break
}
}
}
// Print the longest sub-array
for (let i=beginning;i<beginning+maxLen;i++){
document.write(A[i], ' ' )
}
} // Driver Code let arr = [15, 10, 1, 2, 4, 7, 2] let X = 5 let n = arr.length longestSubarray(arr, n, X) // This code is contributed by Shinjanpatra </script> |
2 4 7 2
Time Complexity: O(N * log(N))
Longest subarray in which absolute difference between any two element is not greater than X using Monotonic Queues:
Maintain a sliding window and keep track of the minimum and maximum element in the window. Keep adding the elements to the window by moving the end pointer till the difference between the maximum and minimum element does not exceed X. If the difference becomes greater than X, then keep decreasing the window by moving the start pointer until the difference becomes less than X. Also pop the elements as the size of the window decreases. Find the longest sliding window with difference less than X and print it.
Maintain a monotonically increasing min queue to keep track of minimum elements and a monotonically decreasing max queue to keep track of maximum elements.
Steps to solve the problem:
-
Initialize two empty dequeues,
minQueue
andmaxQueue
. -
Maintain a variable
ansStart
and
ansEnd
to mark the start and end of largest subarray. - Maintain two pointers start = 0 and end = 0 to mark the range of sliding window.
-
Iterate over all the elements of the array. For each element,
- Pop the elements from the back of minQueue till they are greater than the current element.
- Pop the elements from the back of maxQueue till they are smaller than the current element.
-
Push the current index to both
minQueue
andmaxQueue
. - Compare the minimum element from minQueue and Maximum element from maxQueue. If the difference is greater than X, move start to start + 1 and pop from the queues accordingly.
-
Update
ansStart
and
ansEnd
if the current window has length greater than ans.
-
Return the value of
ans
.
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
int longestSubarray(vector< int >& arr, int X)
{ // Monotonic Queue to store maximum and minimum elements
deque< int > minQueue, maxQueue;
// Pointers to mark the range of current subarray
int n = arr.size(), start = 0, end = 0;
// Pointers to mark the range of maximum subarray
int ansStart = 0, ansEnd = 0;
while (end < n) {
// Pop the elements greater than current element
// from min Queue
while (!minQueue.empty()
&& arr[minQueue.back()] > arr[end])
minQueue.pop_back();
// Pop the elements smaller than current element
// from max Queue
while (!maxQueue.empty()
&& arr[maxQueue.back()] < arr[end])
maxQueue.pop_back();
// Push the current index to both the queues
minQueue.push_back(end);
maxQueue.push_back(end);
// Check if the subarray has maximum difference less
// than X
while (arr[maxQueue.front()] - arr[minQueue.front()]
> X) {
// Reduce the length of sliding window by moving
// the start pointer
if (start == minQueue.front())
minQueue.pop_front();
if (start == maxQueue.front())
maxQueue.pop_front();
start += 1;
}
// Maximize the subarray length
if (end - start > ansEnd - ansStart) {
ansStart = start;
ansEnd = end;
}
end += 1;
}
for ( int i = ansStart; i <= ansEnd; i++)
cout << arr[i] << " " ;
} int main()
{ vector< int > arr{ 15, 10, 1, 2, 4, 7, 2 };
int X = 5;
longestSubarray(arr, X);
return 0;
} |
import java.util.LinkedList;
import java.util.Queue;
class GFG {
public static void main(String[] args) {
LinkedList<Integer> arr = new LinkedList<Integer>();
arr.add( 15 );
arr.add( 10 );
arr.add( 1 );
arr.add( 2 );
arr.add( 4 );
arr.add( 7 );
arr.add( 2 );
int X = 5 ;
LongestSubarray(arr, X);
}
static void LongestSubarray(LinkedList<Integer> arr, int X) {
// Monotonic Queue to store maximum and minimum elements
Queue<Integer> minQueue = new LinkedList<Integer>();
Queue<Integer> maxQueue = new LinkedList<Integer>();
// Pointers to mark the range of the current subarray
int n = arr.size();
int start = 0 , end = 0 ;
// Pointers to mark the range of the maximum subarray
int ansStart = 0 , ansEnd = 0 ;
while (end < n) {
// Pop the elements greater than the current element from min Queue
while (!minQueue.isEmpty() && arr.get(minQueue.peek()) > arr.get(end))
minQueue.poll();
// Pop the elements smaller than the current element from max Queue
while (!maxQueue.isEmpty() && arr.get(maxQueue.peek()) < arr.get(end))
maxQueue.poll();
// Push the current index to both queues
minQueue.offer(end);
maxQueue.offer(end);
// Check if the subarray has a maximum difference less than X
while (arr.get(maxQueue.peek()) - arr.get(minQueue.peek()) > X) {
// Reduce the length of the sliding window by moving the start pointer
if (start == minQueue.peek())
minQueue.poll();
if (start == maxQueue.peek())
maxQueue.poll();
start += 1 ;
}
// Maximize the subarray length
if (end - start > ansEnd - ansStart) {
ansStart = start;
ansEnd = end;
}
end += 1 ;
}
// Print the elements of the longest subarray
for ( int i = ansStart; i <= ansEnd; i++) {
System.out.print(arr.get(i) + " " );
}
}
} |
from collections import deque
def longest_subarray(arr, X):
# Monotonic Queue to store maximum and minimum elements
min_queue, max_queue = deque(), deque()
# Pointers to mark the range of the current subarray
n, start, end = len (arr), 0 , 0
# Pointers to mark the range of the maximum subarray
ans_start, ans_end = 0 , 0
while end < n:
# Pop the elements greater than the current element from the min Queue
while min_queue and arr[min_queue[ - 1 ]] > arr[end]:
min_queue.pop()
# Pop the elements smaller than the current element from the max Queue
while max_queue and arr[max_queue[ - 1 ]] < arr[end]:
max_queue.pop()
# Push the current index to both queues
min_queue.append(end)
max_queue.append(end)
# Check if the subarray has a maximum difference less than X
while arr[max_queue[ 0 ]] - arr[min_queue[ 0 ]] > X:
# Reduce the length of the sliding window by moving the start pointer
if start = = min_queue[ 0 ]:
min_queue.popleft()
if start = = max_queue[ 0 ]:
max_queue.popleft()
start + = 1
# Maximize the subarray length
if end - start > ans_end - ans_start:
ans_start, ans_end = start, end
end + = 1
# Print the elements of the longest subarray
for i in range (ans_start, ans_end + 1 ):
print (arr[i], end = " " )
# Driver code arr = [ 15 , 10 , 1 , 2 , 4 , 7 , 2 ]
X = 5
longest_subarray(arr, X) |
using System;
using System.Collections.Generic;
class GFG
{ static void Main()
{
List< int > arr = new List< int > { 15, 10, 1, 2, 4, 7, 2 };
int X = 5;
LongestSubarray(arr, X);
}
static void LongestSubarray(List< int > arr, int X)
{
// Monotonic Queue to store maximum and minimum elements
Queue< int > minQueue = new Queue< int >();
Queue< int > maxQueue = new Queue< int >();
// Pointers to mark the range of the current subarray
int n = arr.Count;
int start = 0, end = 0;
// Pointers to mark the range of the maximum subarray
int ansStart = 0, ansEnd = 0;
while (end < n)
{
// Pop the elements greater than the current element from min Queue
while (minQueue.Count > 0 && arr[minQueue.Peek()] > arr[end])
minQueue.Dequeue();
// Pop the elements smaller than the current element from max Queue
while (maxQueue.Count > 0 && arr[maxQueue.Peek()] < arr[end])
maxQueue.Dequeue();
// Push the current index to both queues
minQueue.Enqueue(end);
maxQueue.Enqueue(end);
// Check if the subarray has a maximum difference less than X
while (arr[maxQueue.Peek()] - arr[minQueue.Peek()] > X)
{
// Reduce the length of the sliding window by moving the start pointer
if (start == minQueue.Peek())
minQueue.Dequeue();
if (start == maxQueue.Peek())
maxQueue.Dequeue();
start += 1;
}
// Maximize the subarray length
if (end - start > ansEnd - ansStart)
{
ansStart = start;
ansEnd = end;
}
end += 1;
}
// Print the elements of the longest subarray
for ( int i = ansStart; i <= ansEnd; i++)
{
Console.Write(arr[i] + " " );
}
}
} |
function longestSubarray(arr, X) {
// Monotonic Queue to store maximum and minimum elements
const minQueue = [];
const maxQueue = [];
// Pointers to mark the range of current subarray
let n = arr.length;
let start = 0;
let end = 0;
// Pointers to mark the range of maximum subarray
let ansStart = 0;
let ansEnd = 0;
while (end < n) {
// Pop the elements greater than the current element from the min Queue
while (minQueue.length > 0 && arr[minQueue[minQueue.length - 1]] > arr[end]) {
minQueue.pop();
}
// Pop the elements smaller than the current element from the max Queue
while (maxQueue.length > 0 && arr[maxQueue[maxQueue.length - 1]] < arr[end]) {
maxQueue.pop();
}
// Push the current index to both queues
minQueue.push(end);
maxQueue.push(end);
// Check if the subarray has a maximum difference less than X
while (arr[maxQueue[0]] - arr[minQueue[0]] > X) {
// Reduce the length of the sliding window by moving the start pointer
if (start === minQueue[0]) {
minQueue.shift();
}
if (start === maxQueue[0]) {
maxQueue.shift();
}
start += 1;
}
// Maximize the subarray length
if (end - start > ansEnd - ansStart) {
ansStart = start;
ansEnd = end;
}
end += 1;
}
for (let i = ansStart; i <= ansEnd; i++) {
console.log(arr[i] + " " );
}
} // Test const arr = [15, 10, 1, 2, 4, 7, 2]; const X = 5; longestSubarray(arr, X); |
2 4 7 2
Time Complexity: O(N), where N is the size of the array
Auxiliary Space: O(N)