Longest subarray in which absolute difference between any two element is not greater than X
Last Updated :
07 Jan, 2024
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++
#include <bits/stdc++.h>
using namespace std;
void longestSubarray( int * A, int N, int X)
{
int maxLen = 0;
int beginning = 0;
map< int , int > window;
int start = 0, end = 0;
for (; end < N; end++) {
window[A[end]]++;
auto minimum = window.begin()->first;
auto maximum = window.rbegin()->first;
if (maximum - minimum <= X) {
if (maxLen < end - start + 1) {
maxLen = end - start + 1;
beginning = start;
}
}
else {
while (start < end) {
window[A[start]]--;
if (window[A[start]] == 0) {
window.erase(window.find(A[start]));
}
start++;
auto minimum = window.begin()->first;
auto maximum = window.rbegin()->first;
if (maximum - minimum <= X)
break ;
}
}
}
for ( int i = beginning; i < beginning + maxLen; i++)
cout << A[i] << " " ;
}
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
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG
{
static void longestSubarray( int A[], int N, int X)
{
int maxLen = 0 ;
int beginning = 0 ;
TreeMap<Integer, Integer> window = new TreeMap<>();
int start = 0 , end = 0 ;
for (; end < N; end++)
{
window.put(A[end],
window.getOrDefault(A[end], 0 ) + 1 );
int minimum = window.firstKey();
int maximum = window.lastKey();
if (maximum - minimum <= X)
{
if (maxLen < end - start + 1 ) {
maxLen = end - start + 1 ;
beginning = start;
}
}
else {
while (start < end)
{
window.put(A[start],
window.get(A[start]) - 1 );
if (window.get(A[start]) == 0 ) {
window.remove(A[start]);
}
start++;
minimum = window.firstKey();
maximum = window.lastKey();
if (maximum - minimum <= X)
break ;
}
}
}
for ( int i = beginning; i < beginning + maxLen; i++)
System.out.print(A[i] + " " );
}
public static void main(String[] args)
{
int arr[] = { 15 , 10 , 1 , 2 , 4 , 7 , 2 }, X = 5 ;
int n = arr.length;
longestSubarray(arr, n, X);
}
}
|
Python3
def longestSubarray(A, N, X):
maxLen = 0
beginning = 0
window = {}
start = 0
for end in range (N):
if A[end] in window:
window[A[end]] + = 1
else :
window[A[end]] = 1
minimum = min ( list (window.keys()))
maximum = max ( list (window.keys()))
if maximum - minimum < = X:
if maxLen < end - start + 1 :
maxLen = end - start + 1
beginning = start
else :
while start < end:
window[A[start]] - = 1
if window[A[start]] = = 0 :
window.pop(A[start])
start + = 1
minimum = min ( list (window.keys()))
maximum = max ( list (window.keys()))
if maximum - minimum < = X:
break
for i in range (beginning, beginning + maxLen):
print (A[i], end = ' ' )
arr = [ 15 , 10 , 1 , 2 , 4 , 7 , 2 ]
X = 5
n = len (arr)
longestSubarray(arr, n, X)
|
C#
using System;
using System.Linq;
using System.Collections.Generic;
class GFG
{
static void longestSubarray( int [] A, int N, int X)
{
int maxLen = 0;
int beginning = 0;
Dictionary< int , int > window = new Dictionary< int , int >();
int start = 0, end = 0;
for (; end < N; end++)
{
if (!window.ContainsKey(A[end]))
window[A[end]] = 0;
window[A[end]]++;
int minimum = window.Keys.Min();
int maximum = window.Keys.Max();
if (maximum - minimum <= X)
{
if (maxLen < end - start + 1) {
maxLen = end - start + 1;
beginning = start;
}
}
else {
while (start < end)
{
window[A[start]]--;
if (window[A[start]] == 0) {
window.Remove(A[start]);
}
start++;
minimum =window.Keys.Min();
maximum = window.Keys.Max();
if (maximum - minimum <= X)
break ;
}
}
}
for ( int i = beginning; i < beginning + maxLen; i++)
Console.Write(A[i] + " " );
}
public static void Main( string [] args)
{
int [] arr = { 15, 10, 1, 2, 4, 7, 2 };
int X = 5;
int n = arr.Length;
longestSubarray(arr, n, X);
}
}
|
Javascript
<script>
function longestSubarray(A, N, X){
let maxLen = 0
let beginning = 0
let window = new Map()
let start = 0
for (let end=0;end<N;end++){
if (window.has(A[end]))
window.set(A[end],window.get(A[end]) + 1)
else
window.set(A[end] , 1)
let minimum = Math.min(...window.keys())
let maximum = Math.max(...window.keys())
if (maximum - minimum <= X){
if (maxLen < end - start + 1){
maxLen = end - start + 1
beginning = start
}
}
else {
while (start < end){
window.set(A[start],window.get(A[start]) - 1)
if (window.get(A[start]) == 0)
window. delete (A[start])
start += 1
minimum = Math.min(...window.keys())
maximum = Math.max(...window.keys())
if (maximum - minimum <= X)
break
}
}
}
for (let i=beginning;i<beginning+maxLen;i++){
document.write(A[i], ' ' )
}
}
let arr = [15, 10, 1, 2, 4, 7, 2]
let X = 5
let n = arr.length
longestSubarray(arr, n, X)
</script>
|
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
and maxQueue
.
- 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
and maxQueue
.
- 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:
C++
#include <bits/stdc++.h>
using namespace std;
int longestSubarray(vector< int >& arr, int X)
{
deque< int > minQueue, maxQueue;
int n = arr.size(), start = 0, end = 0;
int ansStart = 0, ansEnd = 0;
while (end < n) {
while (!minQueue.empty()
&& arr[minQueue.back()] > arr[end])
minQueue.pop_back();
while (!maxQueue.empty()
&& arr[maxQueue.back()] < arr[end])
maxQueue.pop_back();
minQueue.push_back(end);
maxQueue.push_back(end);
while (arr[maxQueue.front()] - arr[minQueue.front()]
> X) {
if (start == minQueue.front())
minQueue.pop_front();
if (start == maxQueue.front())
maxQueue.pop_front();
start += 1;
}
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;
}
|
Java
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) {
Queue<Integer> minQueue = new LinkedList<Integer>();
Queue<Integer> maxQueue = new LinkedList<Integer>();
int n = arr.size();
int start = 0 , end = 0 ;
int ansStart = 0 , ansEnd = 0 ;
while (end < n) {
while (!minQueue.isEmpty() && arr.get(minQueue.peek()) > arr.get(end))
minQueue.poll();
while (!maxQueue.isEmpty() && arr.get(maxQueue.peek()) < arr.get(end))
maxQueue.poll();
minQueue.offer(end);
maxQueue.offer(end);
while (arr.get(maxQueue.peek()) - arr.get(minQueue.peek()) > X) {
if (start == minQueue.peek())
minQueue.poll();
if (start == maxQueue.peek())
maxQueue.poll();
start += 1 ;
}
if (end - start > ansEnd - ansStart) {
ansStart = start;
ansEnd = end;
}
end += 1 ;
}
for ( int i = ansStart; i <= ansEnd; i++) {
System.out.print(arr.get(i) + " " );
}
}
}
|
Python3
from collections import deque
def longest_subarray(arr, X):
min_queue, max_queue = deque(), deque()
n, start, end = len (arr), 0 , 0
ans_start, ans_end = 0 , 0
while end < n:
while min_queue and arr[min_queue[ - 1 ]] > arr[end]:
min_queue.pop()
while max_queue and arr[max_queue[ - 1 ]] < arr[end]:
max_queue.pop()
min_queue.append(end)
max_queue.append(end)
while arr[max_queue[ 0 ]] - arr[min_queue[ 0 ]] > X:
if start = = min_queue[ 0 ]:
min_queue.popleft()
if start = = max_queue[ 0 ]:
max_queue.popleft()
start + = 1
if end - start > ans_end - ans_start:
ans_start, ans_end = start, end
end + = 1
for i in range (ans_start, ans_end + 1 ):
print (arr[i], end = " " )
arr = [ 15 , 10 , 1 , 2 , 4 , 7 , 2 ]
X = 5
longest_subarray(arr, X)
|
C#
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)
{
Queue< int > minQueue = new Queue< int >();
Queue< int > maxQueue = new Queue< int >();
int n = arr.Count;
int start = 0, end = 0;
int ansStart = 0, ansEnd = 0;
while (end < n)
{
while (minQueue.Count > 0 && arr[minQueue.Peek()] > arr[end])
minQueue.Dequeue();
while (maxQueue.Count > 0 && arr[maxQueue.Peek()] < arr[end])
maxQueue.Dequeue();
minQueue.Enqueue(end);
maxQueue.Enqueue(end);
while (arr[maxQueue.Peek()] - arr[minQueue.Peek()] > X)
{
if (start == minQueue.Peek())
minQueue.Dequeue();
if (start == maxQueue.Peek())
maxQueue.Dequeue();
start += 1;
}
if (end - start > ansEnd - ansStart)
{
ansStart = start;
ansEnd = end;
}
end += 1;
}
for ( int i = ansStart; i <= ansEnd; i++)
{
Console.Write(arr[i] + " " );
}
}
}
|
Javascript
function longestSubarray(arr, X) {
const minQueue = [];
const maxQueue = [];
let n = arr.length;
let start = 0;
let end = 0;
let ansStart = 0;
let ansEnd = 0;
while (end < n) {
while (minQueue.length > 0 && arr[minQueue[minQueue.length - 1]] > arr[end]) {
minQueue.pop();
}
while (maxQueue.length > 0 && arr[maxQueue[maxQueue.length - 1]] < arr[end]) {
maxQueue.pop();
}
minQueue.push(end);
maxQueue.push(end);
while (arr[maxQueue[0]] - arr[minQueue[0]] > X) {
if (start === minQueue[0]) {
minQueue.shift();
}
if (start === maxQueue[0]) {
maxQueue.shift();
}
start += 1;
}
if (end - start > ansEnd - ansStart) {
ansStart = start;
ansEnd = end;
}
end += 1;
}
for (let i = ansStart; i <= ansEnd; i++) {
console.log(arr[i] + " " );
}
}
const arr = [15, 10, 1, 2, 4, 7, 2];
const X = 5;
longestSubarray(arr, X);
|
Time Complexity: O(N), where N is the size of the array
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...