Problem
You are given a 0-indexed integer array nums
. A subarray of nums
is called continuous if:
- Let
i
,i + 1
, …,j
be the indices in the subarray. Then, for each pair of indicesi <= i1, i2 <= j
,0 <= |nums[i1] - nums[i2]| <= 2
.
Return the total number of continuous subarrays.
A subarray is a contiguous non-empty sequence of elements within an array.
Examples
Example 1:
|
|
Example 2:
|
|
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 109
Solution
Method 1 - Sliding window but naive
To determine the total number of continuous subarrays, we can use the sliding window technique. We need to maintain a window that satisfies the given property: for each pair of indices in the subarray, the absolute difference between their values is at most 2.
We’ll use two pointers:
l
to mark the start of the window.r
to mark the end of the window.
As we slide the window, we’ll keep track of the minimum and maximum values within the current subarray. If at any point the condition max(nums[l:r+1]) - min(nums[l:r+1]) <= 2
is violated, we’ll move the starting pointer l
to the right until the condition is again satisfied.
We’ll count the number of subarrays ending at r
for each position of r
by calculating r - l + 1
, which gives us the count of valid subarrays ending at r
.
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n^2)
- The sliding window results in time complexity of
O(n)
but we are again finding min and max elements in window again, resulting in time complexity ofO(n^2)
.
- The sliding window results in time complexity of
- 🧺 Space complexity:
O(1)
apart from the input array, as no additional space proportional to input size is used.
Method 2 - Sliding window using deque
To keep the complexity strictly linear, we can utilize data structures to maintain the minimum and maximum values more efficiently during our sliding window traversal. Specifically, we can use deques (double-ended queues) to maintain a window of the minimum and maximum values.
We can use deque:
- Sliding Window:
- We’ll use two deques: one to keep track of the minimum values (
minDeque
) and one for the maximum values (maxDeque
).
- We’ll use two deques: one to keep track of the minimum values (
- Update Deques:
- As we iterate through each element, we update the deques to include the current element.
- Remove elements from deques if they go out of the current window bounds.
- Adjust Window:
- If the condition
max_deque.peekFirst() - min_deque.peekFirst() > 2
is violated, increment the start pointerl
to shrink the window until the condition is met again.
- If the condition
- Count Valid Subarrays:
- For each valid position of
r
, count the number of continuous subarrays ending atr
by addingr - l + 1
to the answer.
- For each valid position of
Code
|
|
|
|
Complexity
- ⏰ Time complexity:
O(n)
, because each element is processed at most twice (once when added and once when removed from the deques). - 🧺 Space complexity:
O(n)
in the worst case to hold the deque elements.