We need to count every contiguous subarray where the difference between the maximum and minimum element is at most 2. Every single element qualifies on its own, so the question is how far each subarray can extend before the spread grows too large.
The condition "absolute difference between any two elements is at most 2" is equivalent to max(subarray) - min(subarray) <= 2. The max and min are the farthest-apart pair, so if their difference is within 2, every other pair is too. This reduction lets us track two values per subarray instead of comparing all pairs, and it is what makes a sliding window viable.
Two questions drive the solution: for each position, how far can the window extend while keeping max - min <= 2, and how do we maintain the min and max efficiently as elements enter and leave?
1 <= nums.length <= 10^5: an O(n^2) scan can reach 10^10 operations in the worst case, so we want O(n log n) or better. The answer itself can be as large as n(n+1)/2, about 5 x 10^9, which overflows a 32-bit integer, so the count needs a 64-bit type.1 <= nums[i] <= 10^9: values fit in 32 bits, and only their differences matter, so the values themselves cause no overflow.Examine every subarray and check whether its spread (max - min) is within 2. For each starting index i, extend the subarray one element at a time while maintaining a running min and max. Once the spread exceeds 2, stop extending: adding elements can only widen the spread, never shrink it, so no further subarray with the same start can be valid.
count = 0.i from 0 to n-1:currentMin = nums[i] and currentMax = nums[i].j from i to n-1:currentMin = min(currentMin, nums[j]) and currentMax = max(currentMax, nums[j]).currentMax - currentMin > 2, break out of the inner loop.count.count.For nums = [5, 4, 2, 4]:
This restarts the min/max tracking from scratch for every starting index and re-scans the same elements many times. A sliding window avoids the rework: both ends only move forward, so each element is processed a constant number of times.
Maintain a window [left, right] where the spread max - min <= 2. Expand right one step at a time, and whenever the window becomes invalid, shrink from the left until it is valid again.
Shrinking creates a problem that expanding does not. A pair of running min/max variables cannot recover the new min or max after the current min or max leaves the window, because that requires knowing which other values are still inside it.
A sorted frequency map solves this. It stores every value in the window with its count: the first key is the min, the last key is the max, and removing the departing element is a decrement (deleting the key once its count reaches zero). Languages without a sorted map can use a plain hash map and scan the keys for the min and max. Either way the map stays tiny: a valid window spans at most 3 distinct values, and inserting nums[right] adds at most one more, so the map never holds more than 4 keys.
Validity is monotonic: every sub-window of a valid window is valid, and every extension of an invalid window is invalid. So left never needs to move backward, both pointers travel forward at most n steps each, and each element enters and leaves the map exactly once.
The counting step count += right - left + 1 relies on the same monotonicity. After shrinking, [left, right] is the largest valid window ending at right, so the valid subarrays ending at right are exactly those starting at left, left + 1, ..., right. There are right - left + 1 of them, and each subarray is counted once, at the index where it ends.
left = 0, count = 0, and a frequency map of the values in the window.right from 0 to n-1:nums[right] to the frequency map.nums[left], remove the key if its count hits zero, and increment left.(right - left + 1) to count.count.The map stays fast here only because the spread limit of 2 keeps it tiny. Two monotonic deques track the window min and max in O(n) total regardless of the spread limit, and without any sorted-container machinery.
We can replace the sorted map with two monotonic deques: one that tracks the window minimum and one that tracks the window maximum. This is the standard technique for sliding window min/max problems.
The max deque maintains indices in decreasing order of their values. When we add a new element, we pop all indices from the back whose values are less than or equal to it, because they can never be the maximum while the new element is in the window. The front of the deque then always holds the index of the current maximum. The min deque works symmetrically.
The deques store indices rather than values for one reason: when left advances during shrinking, an index smaller than left at the front tells us that entry has fallen out of the window and must be discarded.
left = 0, count = 0, and two deques: maxDeque and minDeque.right from 0 to n-1:right.right.left and pop stale fronts from both deques.(right - left + 1) to count.count.left advances at most n times in total, so all the inner while loops together do O(n) work.