class Solution {
public:
int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
}
};
795. 区间子数组个数
给你一个整数数组 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
原站题解
python3 解法, 执行用时: 284 ms, 内存消耗: 23 MB, 提交时间: 2022-11-24 09:21:43
class Solution: def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int: n = len(nums) l, r = [-1] * n, [n] * n stk = [] for i, v in enumerate(nums): while stk and nums[stk[-1]] <= v: stk.pop() if stk: l[i] = stk[-1] stk.append(i) stk = [] for i in range(n - 1, -1, -1): while stk and nums[stk[-1]] < nums[i]: stk.pop() if stk: r[i] = stk[-1] stk.append(i) return sum((i - l[i]) * (r[i] - i) for i, v in enumerate(nums) if left <= v <= right)
golang 解法, 执行用时: 60 ms, 内存消耗: 7.7 MB, 提交时间: 2022-11-24 09:21:25
// 单调栈 + 枚举元素贡献值 func numSubarrayBoundedMax(nums []int, left int, right int) (ans int) { n := len(nums) l := make([]int, n) r := make([]int, n) for i := range l { l[i], r[i] = -1, n } stk := []int{} for i, v := range nums { for len(stk) > 0 && nums[stk[len(stk)-1]] <= v { stk = stk[:len(stk)-1] } if len(stk) > 0 { l[i] = stk[len(stk)-1] } stk = append(stk, i) } stk = []int{} for i := n - 1; i >= 0; i-- { v := nums[i] for len(stk) > 0 && nums[stk[len(stk)-1]] < v { stk = stk[:len(stk)-1] } if len(stk) > 0 { r[i] = stk[len(stk)-1] } stk = append(stk, i) } for i, v := range nums { if left <= v && v <= right { ans += (i - l[i]) * (r[i] - i) } } return }
golang 解法, 执行用时: 52 ms, 内存消耗: 7.8 MB, 提交时间: 2022-11-24 09:20:43
func numSubarrayBoundedMax(nums []int, left int, right int) int { count := func(lower int) (res int) { cur := 0 for _, x := range nums { if x <= lower { cur++ } else { cur = 0 } res += cur } return } return count(right) - count(left-1) }
python3 解法, 执行用时: 88 ms, 内存消耗: 20.6 MB, 提交时间: 2022-11-24 09:20:26
class Solution: def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int: # 数组 nums 中所有元素小于等于 lower 的子数组数 def count(lower: int) -> int: res = cur = 0 for x in nums: if x <= lower: cur += 1 else: cur = 0 res += cur return res return count(right) - count(left - 1)
golang 解法, 执行用时: 52 ms, 内存消耗: 7.8 MB, 提交时间: 2022-11-24 09:18:52
func numSubarrayBoundedMax(nums []int, left int, right int) (res int) { last2, last1 := -1, -1 for i, x := range nums { if left <= x && x <= right { last1 = i } else if x > right { last2 = i last1 = -1 } if last1 != -1 { res += last1 - last2 } } return }
python3 解法, 执行用时: 84 ms, 内存消耗: 20.8 MB, 提交时间: 2022-11-24 09:18:18
''' 我们可以将数组中的元素分为三类,并分别用 0, 1, 2 来表示: 小于 left,用 0 表示; 大于等于 left 且小于等于 right,用 1 表示; 大于 right,用 2 表示。 那么本题可以转换为求解不包含 2,且至少包含一个 1 的子数组数目。 last1 表示上一次 1 出现的位置,如果不存在则为 −1; last2 表示上一次 2 出现的位置,如果不存在则为 −1。 ''' class Solution: def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int: res = 0 last2 = last1 = -1 for i, x in enumerate(nums): if left <= x <= right: last1 = i elif x > right: last2 = i last1 = -1 if last1 != -1: res += last1 - last2 return res