leetcode 中国区开放了,传送门

该问题地址:点我去看看

问题描述

给定一个元素都是正整数的数组A ,正整数 L 以及 R (L <= R)。

求连续、非空且其中最大元素满足大于等于L 小于等于R的子数组个数。

例如 :
输入: 
A = [2, 1, 4, 3]
L = 2
R = 3
输出: 3
解释: 满足条件的子数组: [2], [2, 1], [3].

解题思路

根据条件 LR ,可以把数字分为三种,分别是 <L>=L 且 <=R 以及 > R。其中 >R 的数据不可能存在与符合条件(最大元素在 L R 之间)的子数组中,所以可以把 >R 的数据看做一堵墙,所有的子数组不可能越过墙。

我们先考虑没有墙的情况。

假设 L R 分别是2 3
假设给定数组[1,1,2,1,1]。(为了简化问题,1代表<L的数,2代表>=L 且 <=R的数)

初始数量 c = 0
遍历数组,遇到前两个1时,数量依然为0,当遇到2时,符合条件的子数组有[1,1,2],[1,2],[2],数量为3,与2的处于低三个位置相对应。此时 c=3

当遇到2后面的1时,新增的符合条件子数组有[1,1,2,1][1,2,1][2,1]
当遇到最后一个1是,新增的符合条件子数组有[1,1,2,1,1][1,2,1,1][2,1,1]
新增的数量也与上一个2的位置有关。

再看个复杂点的例子。比如[1,2,1,2,1,1]
当遍历到最后一个1时,新增的数组为[1,2,1,2,1,1] [2,1,2,1,1] [1,2,1,1] [2,1,1]
该数量与最后遇到的 2 的位置有关。

数组中存在墙的时候,可以看做墙把数组分成一个个子数组,在各个子数组中求子数组个数,最后加一起即可。

js代码实现

var numSubarrayBoundedMax = function(A, L, R) {
    var c_length = 0;       // 记录当前子数组遍历到哪个位置
    var c_last_key_length = 0;   // 记录上一次遇到的 >=L 且 <=R 的数字位置
    var c_sum = 0;  // 记录被墙分开的每段子数组的总和
    var sum = 0;  // 记录总和
    A.forEach(function(e){
        if (e > R){
            sum += c_sum;
            c_length = 0;
            c_last_key_length = 0;
            c_sum = 0;
        }else if (e < L){
            c_length ++;
            c_sum = c_sum + c_last_key_length;
        } else{
            c_length ++;
            c_last_key_length = c_length;
            c_sum += c_length;
        }
    });
    sum += c_sum;
    return sum;
};

Y_xx
520 声望30 粉丝

undefined