Open In App

Longest subarray with absolute difference between any pair at most X

Last Updated : 22 Sep, 2025
Comments
Improve
Suggest changes
12 Likes
Like
Report

Given an integer array arr[] and an integer x, Find the longest sub-array where the absolute difference between any two elements is not greater than x

Examples: 

Input: arr[] = [8, 4, 5, 6, 7], x = 3
Output: [4, 5, 6, 7] 
Explanation: The longest valid subarray is [4, 5, 6, 7] because max = 7, min = 4 → difference = 3 which is less than equal to x.

Input: arr[] = [1, 10, 12, 13, 14], x = 2
Output: [12, 13, 14] 
Explanation: The longest valid subarray is [12, 13, 14] because max = 14, min = 12 → difference = 2 which is less than equal to x.

[Naive Approach] Checking all subarrays - O(n3) Time and O(1) Space

The idea 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.

C++
#include <iostream>
#include<vector>
#include<climits>

using namespace std;

vector<int> longestSubarray(vector<int>& arr, int x) {
    
    int n = arr.size();
    
    int start = 0, maxLen = 1;
    
    for (int i=0; i<n; i++) {
        for (int j=i; j<n; j++) {
            
            // Find minimum and maximum elements
            int mini = INT_MAX, maxi = INT_MIN;
            
            for (int k=i; k<=j; k++) {
                mini = min(mini, arr[k]);
                maxi = max(maxi, arr[k]);
            }
            
            // If difference is less than x,
            // compare length of subarray 
            if (maxi - mini <= x && maxLen < j-i+1) {
                maxLen = j-i+1;
                start = i;
            }
        }
    }
    
    vector<int> res;
    for (int i = start; i < start+maxLen; i++) {
        res.push_back(arr[i]);
    }
    
    return res;
}

int main() {
    vector<int> arr = { 8, 4, 5, 6, 7 };
  	int x = 3;

    vector<int> res = longestSubarray(arr, x);
    
    for (auto val: res) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;

class GfG {
    static ArrayList<Integer> longestSubarray(int[] arr, int x) {
        
        int n = arr.length;
        
        int start = 0, maxLen = 1;
        
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                
                // Find minimum and maximum elements
                int mini = Integer.MAX_VALUE, maxi = Integer.MIN_VALUE;
                
                for (int k = i; k <= j; k++) {
                    mini = Math.min(mini, arr[k]);
                    maxi = Math.max(maxi, arr[k]);
                }
                
                // If difference is less than x,
                // compare length of subarray 
                if (maxi - mini <= x && maxLen < j - i + 1) {
                    maxLen = j - i + 1;
                    start = i;
                }
            }
        }
        
        ArrayList<Integer> res = new ArrayList<>();
        for (int i = start; i < start + maxLen; i++) {
            res.add(arr[i]);
        }
        
        return res;
    }

    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 6, 7 };
        int x = 3;

        ArrayList<Integer> res = longestSubarray(arr, x);
        
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
def longestSubarray(arr, x):
    
    n = len(arr)
    
    start = 0
    maxLen = 1
    
    for i in range(n):
        for j in range(i, n):
            
            # Find minimum and maximum elements
            mini = float('inf')
            maxi = float('-inf')
            
            for k in range(i, j + 1):
                mini = min(mini, arr[k])
                maxi = max(maxi, arr[k])
            
            # If difference is less than x,
            # compare length of subarray 
            if maxi - mini <= x and maxLen < j - i + 1:
                maxLen = j - i + 1
                start = i
    
    return arr[start: start + maxLen]

if __name__ == "__main__":
    arr = [8, 4, 5, 6, 7]
    x = 3

    res = longestSubarray(arr, x)
    
    print(*res)
C#
using System;
using System.Collections.Generic;

class GfG {
    static List<int> longestSubarray(int[] arr, int x) {
        
        int n = arr.Length;
        
        int start = 0, maxLen = 1;
        
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                
                // Find minimum and maximum elements
                int mini = int.MaxValue, maxi = int.MinValue;
                
                for (int k = i; k <= j; k++) {
                    mini = Math.Min(mini, arr[k]);
                    maxi = Math.Max(maxi, arr[k]);
                }
                
                // If difference is less than x,
                // compare length of subarray 
                if (maxi - mini <= x && maxLen < j - i + 1) {
                    maxLen = j - i + 1;
                    start = i;
                }
            }
        }
        
        List<int> res = new List<int>();
        for (int i = start; i < start + maxLen; i++) {
            res.Add(arr[i]);
        }
        
        return res;
    }

    static void Main() {
        int[] arr = {8, 4, 5, 6, 7};
        int x = 3;

        List<int> res = longestSubarray(arr, x);
        
        Console.WriteLine(string.Join(" ", res));
    }
}
JavaScript
function longestSubarray(arr, x) {
    
    let n = arr.length;
    
    let start = 0, maxLen = 1;
    
    for (let i = 0; i < n; i++) {
        for (let j = i; j < n; j++) {
            
            // Find minimum and maximum elements
            let mini = Infinity, maxi = -Infinity;
            
            for (let k = i; k <= j; k++) {
                mini = Math.min(mini, arr[k]);
                maxi = Math.max(maxi, arr[k]);
            }
            
            // If difference is less than x,
            // compare length of subarray 
            if (maxi - mini <= x && maxLen < j - i + 1) {
                maxLen = j - i + 1;
                start = i;
            }
        }
    }
    
    return arr.slice(start, start + maxLen);
}

// Driver Code
let arr = [8, 4, 5, 6, 7];
let x = 3;

let res = longestSubarray(arr, x);
console.log(res.join(" "));

Output
4 5 6 7 

[Better Approach] Using Sliding Window and Sorted Map - O(n * log n) Time and O(n) Space

We use a sliding window with an ordered map to maintain the minimum and maximum values in the current subarray. The window expands until the absolute difference exceeds x; if it does, we shrink the window from the left until the condition is satisfied again.

Working:

  • Maintain two pointers start and end for the window.
  • Insert elements into the map to track min and max.
  • If (max - min) <= x, update the best subarray length.
  • If (max - min) > x, move start forward and remove elements until valid.
  • Finally, return the longest valid subarray found.

In C# and JavaScript, a custom structure is needed for min/max since they don’t have a built-in ordered map.

C++
#include <iostream>
#include <vector>
#include <map>
using namespace std;

vector<int> longestSubarray(vector<int>& arr, int x) {
   
    int n = arr.size();
    int maxLen = 0;
    int beginning = 0;
    map<int, int> window;

    // Initialize the window
    int start = 0, end = 0;
    for (; end < n; end++) {
        
        // Increment the count of that element in the window
        window[arr[end]]++;

        // maximum and minimum element in 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 subarray 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[arr[start]]--;

                // Remove the element from the window
                // if its count is zero
                if (window[arr[start]] == 0) {

                    window.erase(window.find(arr[start]));
                }
                
                // Increment the start of the window
                start++;

                // 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;
            }
        }
    }

    // Return the longest sub-array
    vector<int> res;
    for (int i = beginning; i < beginning + maxLen; i++)
        res.push_back(arr[i]);
        
    return res;
}

int main() {
    vector<int> arr = {8, 4, 5, 6, 7 };
  	int x = 3;

    vector<int> res = longestSubarray(arr, x);
    
    for (auto val: res) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.TreeMap;

class GfG {
    static ArrayList<Integer> longestSubarray(int[] arr, int x) {
        int n = arr.length;
        int maxLen = 0;
        int beginning = 0;

        // map to store the maximum and the minimum elements for
        // a given window
        TreeMap<Integer, Integer> window = new TreeMap<>();
        int start = 0, end = 0;
        for (; end < n; end++) {
            
            // Increment the count of that element in the window
            window.put(arr[end], window.getOrDefault(arr[end], 0) + 1);

            // maximum and minimum element in 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 subarray 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(arr[start], window.get(arr[start]) - 1);

                    // Remove the element from the window
                    // if its count is zero
                    if (window.get(arr[start]) == 0) {
                        window.remove(arr[start]);
                    }
                    
                    // Increment the start of the window
                    start++;

                    // 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;
                }
            }
        }

        // Return the longest sub-array
        ArrayList<Integer> res = new ArrayList<>();
        for (int i = beginning; i < beginning + maxLen; i++)
            res.add(arr[i]);
            
        return res;
    }

    public static void main(String[] args) {
        int[] arr = {8, 4, 5, 6, 7};
        int x = 3;

        ArrayList<Integer> res = longestSubarray(arr, x);
        
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
import bisect

def longestSubarray(arr, x):
    n = len(arr)
    window = []  
    max_len = 0
    start = 0
    beginning = 0
    
    for end in range(n):
    
        # insert arr[end] in sorted order
        bisect.insort(window, arr[end])
    
        # shrink window if max - min > x
        while window[-1] - window[0] > x:
    
            # remove arr[start] from window
            idx = bisect.bisect_left(window, arr[start])
            window.pop(idx)
            start += 1
    
        # update longest subarray
        if end - start + 1 > max_len:
            max_len = end - start + 1
            beginning = start
    
    return arr[beginning:beginning + max_len]


if __name__ == "__main__":
    arr = [8, 4, 5, 6, 7]
    x = 3

    res = longestSubarray(arr, x)
    
    for i in range(0, len(res)):
        print(res[i], end=" ")
C#
using System;
using System.Collections.Generic;
using System.Linq;

// Custom multiset with O(1) min/max tracking
class MultiSet {
    private SortedDictionary<int, int> dict = new SortedDictionary<int, int>();
    private int minVal = int.MaxValue;
    private int maxVal = int.MinValue;

    // Insert element into multiset
    public void Add(int x) {
        if (!dict.ContainsKey(x)) dict[x] = 0;
        dict[x]++;
        if (x < minVal) minVal = x;
        if (x > maxVal) maxVal = x;
    }

    // Remove element from multiset
    public void Remove(int x) {
        if (!dict.ContainsKey(x)) return;
        dict[x]--;
        if (dict[x] == 0) dict.Remove(x);

        // Update min/max if the removed element was min or max
        if (x == minVal || x == maxVal) {
            if (dict.Count == 0) {
                minVal = int.MaxValue;
                maxVal = int.MinValue;
            } else {
                minVal = GetFirstKey();
                maxVal = GetLastKey();
            }
        }
    }

    // Get smallest key in dictionary
    private int GetFirstKey() {
        foreach (var kv in dict) return kv.Key;
        return 0;
    }

    // Get largest key in dictionary
    private int GetLastKey() {
        using (var e = dict.GetEnumerator()) {
            int last = 0;
            while (e.MoveNext()) last = e.Current.Key;
            return last;
        }
    }

    public int Min() => minVal;
    public int Max() => maxVal;
}
    
class GfG {
    static List<int> longestSubarray(int[] arr, int x) {
        int n = arr.Length;
        int maxLen = 0, beginning = 0;
        MultiSet window = new MultiSet();
        int start = 0;

        // Expand the window
        for (int end = 0; end < n; end++) {
            window.Add(arr[end]);

            // Shrink while condition is violated
            while (window.Max() - window.Min() > x) {
                window.Remove(arr[start]);
                start++;
            }

            // Update best window length
            if (end - start + 1 > maxLen) {
                maxLen = end - start + 1;
                beginning = start;
            }
        }

        // Build result subarray
        List<int> res = new List<int>();
        for (int i = beginning; i < beginning + maxLen; i++)
            res.Add(arr[i]);

        return res;
    }

    static void Main() {
        int[] arr = { 8, 4, 5, 6, 7 };
        int x = 3;

        List<int> res = longestSubarray(arr, x);
        Console.WriteLine(string.Join(" ", res));
    }
}
JavaScript
class Heap {
    constructor(compare) {
        this.data = [];
        this.compare = compare;
    }

    size() { return this.data.length; }

    peek() { return this.data[0]; }

    push(val) {
        this.data.push(val);
        this._siftUp(this.data.length - 1);
    }

    pop() {
        if (this.size() === 0) return null;
        const top = this.data[0];
        const last = this.data.pop();
        if (this.size() > 0) {
            this.data[0] = last;
            this._siftDown(0);
        }
        return top;
    }

    _siftUp(i) {
        while (i > 0) {
            const p = (i - 1) >> 1;
            if (this.compare(this.data[i], this.data[p])) {
                [this.data[i], this.data[p]] = [this.data[p], this.data[i]];
                i = p;
            } else break;
        }
    }

    _siftDown(i) {
        const n = this.size();
        while (true) {
            let l = i * 2 + 1, r = i * 2 + 2, best = i;
            if (l < n && this.compare(this.data[l], this.data[best])) best = l;
            if (r < n && this.compare(this.data[r], this.data[best])) best = r;
            if (best !== i) {
                [this.data[i], this.data[best]] = [this.data[best], this.data[i]];
                i = best;
            } else break;
        }
    }
}

function longestSubarray(arr, x) {
    const n = arr.length;
    let maxLen = 0, beginning = 0;

    // frequency map
    const freq = new Map();

    // min-heap and max-heap
    const minHeap = new Heap((a, b) => a < b);
    const maxHeap = new Heap((a, b) => a > b);

    let start = 0;
    for (let end = 0; end < n; end++) {
        freq.set(arr[end], (freq.get(arr[end]) || 0) + 1);
        minHeap.push(arr[end]);
        maxHeap.push(arr[end]);

        // shrink window while invalid
        while (true) {
            while (minHeap.size() > 0 && (freq.get(minHeap.peek()) || 0) === 0)
            minHeap.pop();
            
            while (maxHeap.size() > 0 && (freq.get(maxHeap.peek()) || 0) === 0) 
            maxHeap.pop();

            if (maxHeap.peek() - minHeap.peek() <= x) break;

            freq.set(arr[start], freq.get(arr[start]) - 1);
            start++;
        }

        // update longest window
        if (end - start + 1 > maxLen) {
            maxLen = end - start + 1;
            beginning = start;
        }
    }

    let res = [];
    for (let i = beginning; i < beginning + maxLen; i++) res.push(arr[i]);
    return res;
}


// Driver Code
let arr = [8, 4, 5, 6, 7];
let x = 3;

let res = longestSubarray(arr, x);
console.log(res.join(" "));

Output
4 5 6 7 

[Expected Approach] Using Dequeues - O(n) Time and O(n) Space

We will be using two deques to maintain the minimum and maximum of the current window in O(1). Expand the window while the difference ≤ x, and shrink it when the difference > x to find the longest valid subarray.

Working:

  1. Keep two deques:
    -> minDeque → increasing order (front = minimum).
    -> maxDeque → decreasing order (front = maximum).
  2. Traverse array with end pointer:
    -> Insert element in both deques while maintaining order.
  3. If (maxDeque.front() - minDeque.front()) > x:
    -> Move start pointer forward.
    -> Remove elements from deques if they go out of the window.
  4. Track the maximum window size where difference ≤ x.
C++
#include <iostream>
#include <vector>
#include <deque>

using namespace std;

vector<int> longestSubarray(vector<int>& arr, int x) {
    
    deque<int> minQueue, maxQueue;
    
    int n = arr.size(), start = 0, end = 0;
    
    // Pointers to mark the range of maximum subarray
    int resStart = 0, resEnd = 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();
            
        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 > resEnd - resStart) {
            resStart = start;
            resEnd = end;
        }
        end += 1;
    }

    vector<int> res;
    for (int i = resStart; i <= resEnd; i++)
        res.push_back(arr[i]);
        
    return res;
}

int main() {
    vector<int> arr = { 8, 4, 5, 6, 7 };
  	int x = 3;

    vector<int> res = longestSubarray(arr, x);
    
    for (auto val: res) {
        cout << val << " ";
    }
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;

class GfG {
    static ArrayList<Integer> longestSubarray(int[] arr, int x) {
        
        Deque<Integer> minQueue = new LinkedList<>();
        Deque<Integer> maxQueue = new LinkedList<>();
        
        int n = arr.length, start = 0, end = 0;
        
        int resStart = 0, resEnd = 0;
        while (end < n) {
            
            // Pop the elements greater than current element
            // from min Queue
            while (!minQueue.isEmpty() && arr[minQueue.peekLast()] > arr[end])
                minQueue.pollLast();
                
            // Pop the elements smaller than current element
            // from max Queue
            while (!maxQueue.isEmpty() && arr[maxQueue.peekLast()] < arr[end])
                maxQueue.pollLast();
                
            // Push the current index to both the queues
            minQueue.addLast(end);
            maxQueue.addLast(end);
            
            // Check if the subarray has maximum difference less
            // than x
            while (arr[maxQueue.peekFirst()] - arr[minQueue.peekFirst()] > x) {
                       
                // Reduce the length of sliding window by moving
                // the start pointer
                if (start == minQueue.peekFirst())
                    minQueue.pollFirst();
                if (start == maxQueue.peekFirst())
                    maxQueue.pollFirst();
                start += 1;
            }
            
            // Maximize the subarray length
            if (end - start > resEnd - resStart) {
                resStart = start;
                resEnd = end;
            }
            end += 1;
        }

       
        ArrayList<Integer> res = new ArrayList<>();
        for (int i = resStart; i <= resEnd; i++)
            res.add(arr[i]);
            
        return res;
    }

    public static void main(String[] args) {
        int[] arr = { 8, 4, 5, 6, 7 };
        int x = 3;

        ArrayList<Integer> res = longestSubarray(arr, x);
        
        for (int val : res) {
            System.out.print(val + " ");
        }
        System.out.println();
    }
}
Python
from collections import deque

def longestSubarray(arr, x):
    
    minQueue = deque()
    maxQueue = deque()
    
    n = len(arr)
    start = end = 0
    
    resStart = resEnd = 0
    while end < n:
        
        # Pop the elements greater than current element
        # from min Queue
        while minQueue and arr[minQueue[-1]] > arr[end]:
            minQueue.pop()
            
        # Pop the elements smaller than current element
        # from max Queue
        while maxQueue and arr[maxQueue[-1]] < arr[end]:
            maxQueue.pop()
            
        # Push the current index to both the queues
        minQueue.append(end)
        maxQueue.append(end)
        
        # Check if the subarray has maximum difference less
        # than x
        while arr[maxQueue[0]] - arr[minQueue[0]] > x:
                   
            # Reduce the length of sliding window by moving
            # the start pointer
            if start == minQueue[0]:
                minQueue.popleft()
            if start == maxQueue[0]:
                maxQueue.popleft()
            start += 1
        
        # Maximize the subarray length
        if end - start > resEnd - resStart:
            resStart, resEnd = start, end

        end += 1

  
    return arr[resStart:resEnd+1]

if __name__ == "__main__":
    arr = [8, 4, 5, 6, 7]
    x = 3

    res = longestSubarray(arr, x)
    
    print(*res)
C#
using System;
using System.Collections.Generic;

class GfG {

    static List<int> longestSubarray(int[] arr, int x) {
        
        LinkedList<int> minQueue = new LinkedList<int>();
        LinkedList<int> maxQueue = new LinkedList<int>();
        
        int n = arr.Length, start = 0, end = 0;
        
        int resStart = 0, resEnd = 0;
        while (end < n) {
            
            // Pop the elements greater than current element
            // from min Queue
            while (minQueue.Count > 0 && arr[minQueue.Last.Value] > arr[end])
                minQueue.RemoveLast();
                
            // Pop the elements smaller than current element
            // from max Queue
            while (maxQueue.Count > 0 && arr[maxQueue.Last.Value] < arr[end])
                maxQueue.RemoveLast();
                
            // Push the current index to both the queues
            minQueue.AddLast(end);
            maxQueue.AddLast(end);
            
            // Check if the subarray has maximum difference less
            // than x
            while (arr[maxQueue.First.Value] - arr[minQueue.First.Value] > x) {
                       
                // Reduce the length of sliding window by moving
                // the start pointer
                if (start == minQueue.First.Value)
                    minQueue.RemoveFirst();
                if (start == maxQueue.First.Value)
                    maxQueue.RemoveFirst();
                start += 1;
            }
            
            // Maximize the subarray length
            if (end - start > resEnd - resStart) {
                resStart = start;
                resEnd = end;
            }
            end += 1;
        }

        // Return the longest sub-array
        List<int> res = new List<int>();
        for (int i = resStart; i <= resEnd; i++)
            res.Add(arr[i]);
            
        return res;
    }

    static void Main() {
        int[] arr = { 8, 4, 5, 6, 7 };
        int x = 3;

        List<int> res = longestSubarray(arr, x);
        
        Console.WriteLine(string.Join(" ", res));
    }
}
JavaScript
function longestSubarray(arr, x) {
    let minQueue = []; 
    let maxQueue = []; 
    
    let start = 0, end = 0, resStart = 0, resEnd = 0;
    
    while (end < arr.length) {
        
        // Maintain minQueue: remove elements greater than current
        while (minQueue.length && arr[minQueue[minQueue.length - 1]] > arr[end])
            minQueue.pop();
        
        // Maintain maxQueue: remove elements smaller than current
        while (maxQueue.length && arr[maxQueue[maxQueue.length - 1]] < arr[end])
            maxQueue.pop();
            
        minQueue.push(end);
        maxQueue.push(end);
    
        // Shrink window if difference exceeds x
        while (arr[maxQueue[0]] - arr[minQueue[0]] > x) {
            if (start === minQueue[0]) minQueue.shift();
            if (start === maxQueue[0]) maxQueue.shift();
            start++;
        }
    
        // Update result if current window is longer
        if (end - start > resEnd - resStart) {
            resStart = start;
            resEnd = end;
        }
    
        end++;
    }
    
    // Return the longest subarray satisfying the condition
    return arr.slice(resStart, resEnd + 1);

}

// Driver Code
let arr = [8, 4, 5, 6, 7];
let x = 3;
const res = longestSubarray(arr, x);
console.log(res.join(" "));

Output
4 5 6 7 

Article Tags :

Explore