Description Link to heading

795. Number of Subarrays with Bounded Maximum (Medium) Given an integer array nums and two integers left and right, return the number of contiguous non-empty subarrays such that the value of the maximum array element in that subarray is in the range [left, right].

The test cases are generated so that the answer will fit in a 32-bit integer.

Example 1:

Input: nums = [2,1,4,3], left = 2, right = 3
Output: 3
Explanation: There are three subarrays that meet the requirements: [2], [2, 1], [3].

Example 2:

Input: nums = [2,9,2,5,6], left = 2, right = 8
Output: 7

Constraints:

  • 1 <= nums.length <= 10⁵
  • 0 <= nums[i] <= 10⁹
  • 0 <= left <= right <= 10⁹

Solution Link to heading

Monotone stack Link to heading

When we encounter problems concerning the maximum value within a continuous interval, the application of a monotonic stack is worth considering.

For nums[idx], we aim to determine the quantity of subarrays where nums[idx] is the maximum value. Let lidx be the largest l that satisfies nums[l] >= nums[idx] and l < idx; let ridx be the smallest r that satisfies nums[r] > nums[idx] and r > idx. Our task is to enumerate all idx that satisfy 0 <= idx < n, find the corresponding lidx and ridx, and thereby calculate the quantity of subarrays.

The quantity of subarrays equals (ridx - idx) * (idx - lidx)

In this problem, we can consider using a stack that decreases monotonically from the bottom to the top to find ridx and lidx. Note that the elements in the stack are indices idx. When enumerating i, if nums[i] > nums[stk.top()], for idx = stk.top(), pop the top element of the stack, ridx = i, lidx is the new top of the stack, if the stack is empty, then lidx = -1.

After enumerating i, for the remaining elements in the stack, idx = stk.top(), ridx = n, pop the elements in the stack, if the stack is empty, lidx = -1, otherwise lidx = stk.top();.

Code Link to heading

Monotone stack Link to heading

class Solution {
  public:
    int numSubarrayBoundedMax(vector<int> &nums, int left, int right) {
        int res = 0;
        stack<int> stk;
        int n = nums.size();
        for (int i = 0; i < n; ++i) {
            while (!stk.empty() && nums[i] > nums[stk.top()]) {
                int idx = stk.top();
                int len1 = i - idx;
                int val = nums[idx];
                stk.pop();
                int len2 = stk.empty() ? idx + 1 : idx - stk.top();
                if (val <= right && val >= left) {
                    res += len1 * len2;
                }
            }
            stk.push(i);
        }
        while (!stk.empty()) {
            int idx = stk.top();
            int len1 = n - idx;
            int val = nums[idx];
            stk.pop();
            int len2 = stk.empty() ? idx + 1 : idx - stk.top();
            if (val <= right && val >= left) {
                res += len1 * len2;
            }
        }
        return res;
    }
};