28. Longest Bounded-Difference Subarray
β GFG solution to the Longest Bounded-Difference Subarray problem: find maximum length subarray where absolute difference between any two elements β€ x using monotonic deque technique. π
The problem can be found at the following link: π Question Link
π§© Problem Description
Given an array of positive integers arr[]
and a non-negative integer x
, the task is to find the longest sub-array where the absolute difference between any two elements is not greater than x
.
If multiple such subarrays exist, return the one that starts at the smallest index.
A subarray is considered valid if for any two elements arr[i]
and arr[j]
in the subarray, |arr[i] - arr[j]| β€ x
.
π Examples
Example 1
Input: arr[] = [8, 4, 5, 6, 7], x = 3
Output: [4, 5, 6, 7]
Explanation: The sub-array described by index [1..4], i.e. [4, 5, 6, 7]
contains no two elements whose absolute difference is greater than 3.
Max difference = 7 - 4 = 3, which is β€ x.
Example 2
Input: arr[] = [1, 10, 12, 13, 14], x = 2
Output: [12, 13, 14]
Explanation: The sub-array described by index [2..4], i.e. [12, 13, 14]
contains no two elements whose absolute difference is greater than 2.
Max difference = 14 - 12 = 2, which is β€ x.
Example 3
Input: arr[] = [5, 5, 5, 5], x = 0
Output: [5, 5, 5, 5]
Explanation: All elements are identical, so the absolute difference between
any two elements is 0, which satisfies the condition x = 0.
π Constraints
$1 \le \text{arr.size()} \le 10^5$
$1 \le \text{arr}[i] \le 10^9$
$0 \le x \le 10^9$
β
My Approach
The optimal approach uses the Sliding Window technique with Monotonic Deques to efficiently track minimum and maximum elements in the current window:
Sliding Window + Monotonic Deques
Initialize Data Structures:
Use two deques:
minQ
(maintains indices in increasing order of values) andmaxQ
(maintains indices in decreasing order of values).Use two pointers:
l
(left boundary) andr
(right boundary) of the sliding window.Track
maxLen
andstart
position for the result.
Expand Window (Right Pointer):
For each
r
, maintain monotonic property:Remove indices from
minQ
back whilearr[back] >= arr[r]
Remove indices from
maxQ
back whilearr[back] <= arr[r]
Add current index
r
to both deques.
Contract Window (Left Pointer):
While
arr[maxQ.front()] - arr[minQ.front()] > x
:Remove outdated indices from deque fronts if they equal
l
Increment
l
to shrink window from left
Update Result:
After each valid window, update
maxLen
andstart
position if current window is larger.
Return Result:
Extract subarray from
start
tostart + maxLen
.
Key Insight: In any subarray, the maximum absolute difference equals max_element - min_element
. Using monotonic deques allows O(1) access to min/max values in the current window.
π Time and Auxiliary Space Complexity
Expected Time Complexity: O(n), where n is the size of the array. Each element is added and removed from deques at most once, making it linear time.
Expected Auxiliary Space Complexity: O(n), where n is the maximum number of elements that can be stored in the deques in the worst case.
π§βπ» Code (C++)
class Solution {
public:
vector<int> longestSubarray(vector<int>& arr, int x) {
deque<int> minQ, maxQ;
int n = arr.size(), l = 0, r = 0, start = 0, len = 0;
while (r < n) {
while (!minQ.empty() && arr[minQ.back()] >= arr[r]) minQ.pop_back();
while (!maxQ.empty() && arr[maxQ.back()] <= arr[r]) maxQ.pop_back();
minQ.push_back(r);
maxQ.push_back(r);
while (arr[maxQ.front()] - arr[minQ.front()] > x) {
if (l == minQ.front()) minQ.pop_front();
if (l == maxQ.front()) maxQ.pop_front();
l++;
}
if (r - l + 1 > len) {
len = r - l + 1;
start = l;
}
r++;
}
return vector<int>(arr.begin() + start, arr.begin() + start + len);
}
};
β Code (Java)
class Solution {
public ArrayList<Integer> longestSubarray(int[] arr, int x) {
ArrayDeque<Integer> minQ = new ArrayDeque<>(), maxQ = new ArrayDeque<>();
int n = arr.length, l = 0, start = 0, maxLen = 0;
for (int r = 0; r < n; r++) {
while (!minQ.isEmpty() && arr[minQ.peekLast()] >= arr[r]) minQ.removeLast();
while (!maxQ.isEmpty() && arr[maxQ.peekLast()] <= arr[r]) maxQ.removeLast();
minQ.addLast(r);
maxQ.addLast(r);
while (arr[maxQ.peekFirst()] - arr[minQ.peekFirst()] > x) {
if (l == minQ.peekFirst()) minQ.removeFirst();
if (l == maxQ.peekFirst()) maxQ.removeFirst();
l++;
}
if (r - l + 1 > maxLen) {
maxLen = r - l + 1;
start = l;
}
}
ArrayList<Integer> result = new ArrayList<>();
for (int i = start; i < start + maxLen; i++) result.add(arr[i]);
return result;
}
}
π Code (Python)
class Solution:
def longestSubarray(self, arr, x):
from collections import deque
minQ, maxQ = deque(), deque()
n, l, start, maxLen = len(arr), 0, 0, 0
for r in range(n):
while minQ and arr[minQ[-1]] >= arr[r]: minQ.pop()
while maxQ and arr[maxQ[-1]] <= arr[r]: maxQ.pop()
minQ.append(r)
maxQ.append(r)
while arr[maxQ[0]] - arr[minQ[0]] > x:
if l == minQ[0]: minQ.popleft()
if l == maxQ[0]: maxQ.popleft()
l += 1
if r - l + 1 > maxLen:
maxLen = r - l + 1
start = l
return arr[start:start + maxLen]
π§ Contribution and Support
For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: π¬ Any Questions?. Let's make this learning journey more collaborative!
β If you find this helpful, please give this repository a star! β
πVisitor Count
Last updated