一、题目
题目:给你一个整数数组 nums 和两个整数:left 及 right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。
二、思路
1、单调栈
本题给定了区间【left,right】,首先可以想到依次遍历,找到每个在区间内的数,看他们可以构成的子数组有哪些。
进而可以想到,看以该数为右端点的数组,有多少满足条件的子数组。(其实这也是一种解法)
想到此处,我们可以想到,如果该数在区间【left,right】内,以该数为子数组的最大数一定满足条件。单调栈可以快速找到第一个比该数大(小)的数,找到每个数左右第一个比其大的数记其位置为l,r
①如果该数在区间【left,right】中,(r-i) *(i-l) 为以该数为子数组最大数组满足题目要求的数量
②否则以该数为最大数的子数组一定不满足条件
过程:
先自左至右找到每个数右边第一个大于自身的数的坐标,存在数组R中。
再自右至左找到每个数左边第一个大于自身的数的坐标,存在数组L中。
最后遍历数组,如果在区间内,就统计以该数为最大数的子数组的个数。
TIPS:
为了防止重复,可将一个< 改为 <=
示例图
自左至右找到每个数右边第一个大于自身的数的坐标,存在数组R中。
自右至左找到每个数左边第一个大于自身的数的坐标,存在数组L中。
遍历数组,如果在区间内,就统计以该数为最大数的子数组的个数。
二、代码
python
代码如下:
class Solution:
def numSubarrayBoundedMax(self, nums, left: int, right: int) -> int:
n = len(nums)
l,r = [-1]*n,[n]*n
stack = []
res = 0
for i in range(n):
while stack and nums[stack[-1]] < nums[i]:
r[stack.pop()] = i
stack.append(i)
stack = []
for j in range(n-1,-1,-1):
while stack and nums[stack[-1]] <= nums[j]:
l[stack.pop()] = j
stack.append(j)
for i in range(n):
if left <= nums[i] <= right:
res += (i-l[i])*(r[i]-i)
return res