795. 区间子数组个数

29 阅读1分钟

给你一个整数数组 nums 和两个整数:left 及 right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。

生成的测试用例保证结果符合 32-bit 整数范围。

 

示例 1:

输入: nums = [2,1,4,3], left = 2, right = 3
输出: 3
解释: 满足条件的三个子数组:[2], [2, 1], [3]

示例 2:

输入: nums = [2,9,2,5,6], left = 2, right = 8
输出: 7

 

提示:

  • 1 <= nums.length <= 105
  • 0 <= nums[i] <= 109
  • 0 <= left <= right <= 109

题解:

/**
 * @param {number[]} nums
 * @param {number} left
 * @param {number} right
 * @return {number}
 */
//  方法一:一次遍历
var numSubarrayBoundedMax = function (nums, left, right) {
    let res = 0, last2 = -1, last1 = -1;
    for (let i = 0; i < nums.length; i++) {
        // 当前值满足条件时 last1 等于当前位置
        // 否则last2 等于当前位置 last1 值为-1
        if (nums[i] >= left && nums[i] <= right) {
            last1 = i
        } else if (nums[i] > right) {
            last2 = i
            last1 = -1
        }
        // 子数组若以 i 为右端点,合法的左端点可以落在(last2, last1]
        // 这样的左端点共有last1 - last2个
        if (last1 != -1) {
            res += last1 - last2
        }
    }
    return res
};
// 方法二:计数
var numSubarrayBoundedMax = function (nums, left, right) {
    // count(nums, right) => 获取满足小等于right 的值
    // count(nums, left-1) => 获取满足小left 的值
    return count(nums, right) - count(nums, left - 1)
}
var count = function (nums, lows) {
    let cur = 0, res = 0;
    for (let x of nums) {
        cur = x <= lows ? cur + 1 : 0
        res += cur
    }
    return res
}