
Problem Statement
Given an array nums
of integers and an integer limit
, you are required to determine the length of the longest contiguous subarray where the absolute difference between any two elements within the subarray does not exceed the limit
. It is essential that the subarray, whose length you are calculating, is non-empty. The task encapsulates understanding the variability within the subarray that fits under the defined threshold to ensure that it remains the longest while adhering to the condition of the limit on absolute differences between its elements.
Examples
Example 1
Input:
nums = [8,2,4,7], limit = 4
Output:
2
Explanation:
All subarrays are: [8] with maximum absolute diff |8-8| = 0 <= 4. [8,2] with maximum absolute diff |8-2| = 6 > 4. [8,2,4] with maximum absolute diff |8-2| = 6 > 4. [8,2,4,7] with maximum absolute diff |8-2| = 6 > 4. [2] with maximum absolute diff |2-2| = 0 <= 4. [2,4] with maximum absolute diff |2-4| = 2 <= 4. [2,4,7] with maximum absolute diff |2-7| = 5 > 4. [4] with maximum absolute diff |4-4| = 0 <= 4. [4,7] with maximum absolute diff |4-7| = 3 <= 4. [7] with maximum absolute diff |7-7| = 0 <= 4. Therefore, the size of the longest subarray is 2.
Example 2
Input:
nums = [10,1,2,4,7,2], limit = 5
Output:
4
Explanation:
The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5.
Example 3
Input:
nums = [4,2,2,2,4,4,2,2], limit = 0
Output:
3
Constraints
1 <= nums.length <= 105
1 <= nums[i] <= 109
0 <= limit <= 109
Approach and Intuition
Understanding how to find the longest subarray where the absolute difference between any two elements does not exceed a certain limit
can be tricky. Here's an intuitive way to approach solving this problem:
Maintaining Range Information with a Deque: By using a double-ended queue (deque), we can efficiently manage the maximum and minimum elements in window slices of the array, which helps in checking the limit condition.
Sliding Window Technique:
- Traverse through the array using two pointers to mark the boundaries of our current subarray (window); let's call them
start
andend
. - Incrementally expand the
end
pointer to include elements in the subarray and update our deque structure to add elements in order while ensuring we maintain them from largest to smallest. - At each step, compare the maximum and minimum of the current subarray to check if they comply with the
limit
. - If the condition violates, move the
start
pointer to shrink the subarray until it satisfies the condition. - Keep track of the size of subarrays which meet the condition and update the maximum size encountered.
- Traverse through the array using two pointers to mark the boundaries of our current subarray (window); let's call them
Edge Cases Handling:
- When
nums
has only one element, the answer will always be 1 because there's no other element to compare to. - Consider different edge cases especially when
limit
is 0, which forces all elements of the valid subarray to be identical. Use this information to optimize the solution.
- When
By applying these strategies, the problem becomes one of optimally managing and updating a window of elements such that at each step, we try to maintain a valid and as large as possible subarray segment that fits within the described limits of maximum absolute difference. The use of data structures like deque ensures that operations to find maximum and minimum, which are integral to our checks against the limit, are efficient.
Solutions
- C++
- Java
- Python
class Solution {
public:
int maxSubarrayWithLimit(vector<int>& data, int threshold) {
deque<int> highestValues, lowestValues;
int start = 0, end;
int maxLen = 0;
for (end = 0; end < data.size(); ++end) {
while (!highestValues.empty() && highestValues.back() < data[end]) {
highestValues.pop_back();
}
highestValues.push_back(data[end]);
while (!lowestValues.empty() && lowestValues.back() > data[end]) {
lowestValues.pop_back();
}
lowestValues.push_back(data[end]);
while (highestValues.front() - lowestValues.front() > threshold) {
if (highestValues.front() == data[start]) {
highestValues.pop_front();
}
if (lowestValues.front() == data[start]) {
lowestValues.pop_front();
}
++start;
}
maxLen = max(maxLen, end - start + 1);
}
return maxLen;
}
};
The provided C++ solution aims to calculate the length of the longest subarray where the absolute difference between the maximum and minimum elements is less than or equal to a given threshold. The solution employs the following steps:
- Initialize two deques to maintain the highest and lowest values encountered while traversing the array.
- Use two pointers,
start
andend
, to represent the current subarray being considered. - Iterate through the array using the
end
pointer. For each element:- Update the
highestValues
deque by removing elements from the back until the current element is less than or equal to the last element in the deque, and then add the current element to the deque. - Similarly, update the
lowestValues
deque by removing elements from the back until the current element is greater than or equal to the last element in the deque, and then add the current element to the deque. - If the difference between the front of the
highestValues
andlowestValues
exceeds the threshold, adjust thestart
pointer to reduce the subarray size until the condition is met.
- Update the
- Calculate the length of the current subarray and update
maxLen
if the current subarray is longer. - Return
maxLen
as the result, which is the maximum length of a subarray that meets the criteria.
This approach efficiently handles the varying conditions of the subarray with the help of two deques, allowing for dynamic adjustment of the subarray boundaries based on the two-pointer technique. The solution guarantees that each element is processed in constant time on average, leading to an overall linear time complexity. This method is effective for handling large datasets and ensures optimal performance.
class Solution {
public int findLongestSubarray(int[] array, int threshold) {
Deque<Integer> descDeque = new LinkedList<>();
Deque<Integer> ascDeque = new LinkedList<>();
int start = 0;
int longest = 0;
for (int end = 0; end < array.length; ++end) {
// Keep descDeque in descending order
while (!descDeque.isEmpty() && descDeque.peekLast() < array[end]) {
descDeque.pollLast();
}
descDeque.offerLast(array[end]);
// Keep ascDeque in ascending order
while (!ascDeque.isEmpty() && ascDeque.peekLast() > array[end]) {
ascDeque.pollLast();
}
ascDeque.offerLast(array[end]);
// Ensure the window is within the allowed limit
while (descDeque.peekFirst() - ascDeque.peekFirst() > threshold) {
if (descDeque.peekFirst() == array[start]) {
descDeque.pollFirst();
}
if (ascDeque.peekFirst() == array[start]) {
ascDeque.pollFirst();
}
++start;
}
longest = Math.max(longest, end - start + 1);
}
return longest;
}
}
This Java solution finds the length of the longest continuous subarray where the absolute difference between any two elements is less than or equal to a given threshold. The approach utilizes two deques to maintain a window of values that can expand and contract based on the provided conditions:
- DescDeque maintains values in descending order.
- AscDeque maintains values in ascending order.
As you iterate through the array,
- Add new elements appropriately to both Deques to maintain their order.
- Check if the difference between the first elements of the two deques exceeds the threshold. If it does, adjust the starting index of the window accordingly.
- At each step, calculate the length of the current valid subarray, and update the maximum length found.
The algorithm efficiently handles updates to the window size and keeps track of the current and maximum lengths of subarrays that meet the condition using the following approach:
- Expand the window by adding elements to the back of each deque.
- Contract the window from the start if the condition is violated.
- Maintain the maximum length encountered during traversal.
Ultimately, the function returns the size of the longest subarray that satisfies the given conditions. This method ensures that edge cases, like single element arrays or no valid subarray exceeding the threshold, are handled correctly by the robust update mechanism of the deques.
class Solution:
def findLongestSubarray(self, numbers: List[int], threshold: int) -> int:
ascending = deque()
descending = deque()
start = 0
longest = 0
for end in range(len(numbers)):
# Descending deque maintains the largest elements at the front
while descending and descending[-1] < numbers[end]:
descending.pop()
descending.append(numbers[end])
# Ascending deque maintains the smallest elements at the front
while ascending and ascending[-1] > numbers[end]:
ascending.pop()
ascending.append(numbers[end])
# Adjust the window size if the difference exceeds the threshold
while descending[0] - ascending[0] > threshold:
if descending[0] == numbers[start]:
descending.popleft()
if ascending[0] == numbers[start]:
ascending.popleft()
start += 1
# Update the longest length found
longest = max(longest, end - start + 1)
return longest
To solve the problem of finding the longest continuous subarray where the absolute difference between any two elements is less than or equal to a given limit, this Python solution utilizes the double-ended queue (deque) data structure for efficient element addition and removal at both ends.
- Initialize two deques,
ascending
anddescending
, to keep track of minimum and maximum values in the current window, respectively. - Use two pointers,
start
andend
, to represent the current window's bounds. - Iterate through the
numbers
array using theend
pointer. - For the
descending
deque, remove elements from the back until the current number is less than or equal to the last element in the deque and then append the current number. This ensures that the highest elements are always at the front. - Similarly, for the
ascending
deque, remove elements from the back until the current number is greater than or equal to the last element and append the current number. This keeps the lowest elements at the front. - If the difference between the maximum (front of
descending
) and the minimum (front ofascending
) exceeds thethreshold
, adjust thestart
pointer:- Remove the
start
element from the deques if it matches their front element. - Increment the
start
pointer.
- Remove the
- Continuously update the
longest
length of the subarray as the difference betweenend
andstart
plus one.
Once the loop completes, return the value of longest
, which contains the size of the longest subarray meeting the condition. This approach effectively maintains the range of values in the current window, allowing for fast updates and checks against the threshold condition.
No comments yet.