leetcode 795. Number of Subarrays with Bounded Maximum
题目描述
We are given an array A
of positive integers, and two positive integers L
and R (L <= R)
.
Return the number of (contiguous, non-empty) subarrays such that the value of the maximum array element in that subarray is at least L
and at most R
.
Note:
- L, R and
A[i]
will be an integer in the range[0, 10^9]
. - The length of
A
will be in the range of[1, 50000]
.
Difficulty: Medium
795. Number of Subarrays with Bounded Maximum
中文描述
给你一个包含全是正整数的列表A
,找出所有连续的子序列,满足区间里的最大值不超过R
,最小不小于L
的个数。
输入格式
输入一个列表A
,列表元素的集合。R
表示最大值,L
表示最小值。
Examples:
- Input: A = [2, 1, 4, 3],L = 2,R = 3
Output: 3
解释:
由A子序列满足条件的有 [2],[2,1],[3]总计3种.
解答思路
解法一:划分区间
1.找出A中所有大于R的元素,任何区间包含这些元素则不可能满足要求,所以以此为界,划分区间。
2.逐个遍历划分后的区间,计算每个区间能够满足题意的小区间个数。
3.如何从区间找到满足要求的小区间,我是这样做的。每个区间从后往前遍历元素,如果该元素不小于L,则说明以这个元素为开头的所有区间都能满足要求。所以有该区间末尾的位置减去当前元素的位置这么多个区间满足要求。如果元素小于L,则,表示和上一个元素能提供的小区间数一样。最后累加就能得到最后个数。
4.需要两次遍历,复杂度估计 O(n) O ( n )
代码
解法一,速度超慢= =,
class Solution(object):
def numSubarrayBoundedMax(self, A, L, R):
"""
:type A: List[int]
:type L: int
:type R: int
:rtype: int
123ms
"""
# 找出所有比R大的元素的位置
bigger_R = []
for i, a in enumerate(A):
if a > R:
bigger_R.append(i)
start = 0
sub_range = []
# 按比R大的元素把原来区间划分为更小的区间
for high in bigger_R:
if high > start:
sub_range.append((start, high))
start = high + 1
# 考虑最后一段需不需要加入
if start < len(A):
sub_range.append((start, len(A)))
# print(sub_range)
# 对每个区间的值相加
ans = 0
for one_range in sub_range:
before_one = 0
for i in range(one_range[1] - 1, one_range[0] - 1, -1):
if A[i] >= L:
before_one = one_range[1] - i
ans += before_one
return ans
参考了其它人写的代码,比我写的简介多了,思路一样:
class Solution(object):
def numSubarrayBoundedMax(self, A, L, R):
"""
:type A: List[int]
:type L: int
:type R: int
:rtype: int
111ms
"""
res, dp = 0, 0
prev = -1
for i in range(len(A)):
if A[i] < L and i > 0:
res += dp
if A[i] > R:
dp = 0
prev = i
if L <= A[i] <= R:
dp = i - prev
res += dp
return res