795. Number of Subarrays with Bounded Maximum

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 <= 105
  • 0 <= nums[i] <= 109
  • 0 <= left <= right <= 109

题目:给定一串数组,和左右边界left, right。返回连续非空子数组的个数,这些子数组需要满足的条件是:子数组中最大值要在left和right之间。

思路:

1, 当子数组都在left,right之间时:left=2, right=8, nums=[2, 5, 6]. 子数组个数为 [2],[5],[6],[2,5],[5,6],[2,5,6], 3 + 2 + 1 = 6;可以看出,后面每新增一个在[left, right]中间的值都增加了n个符合条件的子序列。例如nums=[2, 5, 6, 7]的话,比之前增加[2, 5, 6, 7],[5,6,7],[6,7],[7],4个符合条件的子序列。即[2, 5, 6, 7]符合条件的子序列为4+3+2+1=10;

2,当子数组最后一个值比left小时:left=2, right=8, nums=[2, 5, 1]. 子数组个数为[2],[5],[2,5],[5,1], [2, 5, 1] , 2 + 2 + 1 = 5;  比第一种情况少了[1],1个,也就是说最后的值比left小的话只贡献了[5, 1]和[2, 5, 1] 2个;如果子序列变为[2, 5, 1, 1],则最后一个1新增的符合条件的子序列为[2, 5, 1, 1]和[5, 1, 1]。新增的符合条件子序列个数为n - Cmin个。Cmin为当前连续的比left小的元素个数。这里为[1, 1],Cmin=2, n = 4.因此最后一个元素1贡献的子序列个数为2;

3, 当子数字最后一个值比right大时:left=2, right=8, nums=[2, 5, 9],则最后一个元素9贡献的子数组个数为0,因为只要包含9,则子序列最大值都不符合条件了。

因此,可以线性扫描,用start记录当前子序列最靠前的开始点,扫描到新的值nums[i]时有三种情况:

        1,nums[i] > right :这种最简单,结果数不变,将更新start为i+1,以确保子序列不包含nums[i];

        2, nums[i]  <  left: 更新Cmin++, 更新结果 res += i - start + 1 - Cmin. 

        3, left <= nums[i] <= right:更新Cmin=0, 更新结果

代码:

class Solution {
public:
    int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
        int res = 0, start = 0;
        int Cmin = 0; //记录连续的比left小的元素个数
        for(int i = 0; i < nums.size(); i++){
            if(nums[i] > right) {
                start = i + 1;
                Cmin = 0;
            } else if(nums[i] < left){
                Cmin++;
                res += i - start + 1 - Cmin;
            } else {
                Cmin = 0;
                res += i - start + 1;
            }
        }
        return res;
    }
};

 time:O(N), space: O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值