795.区间子数组个数

【LetMeFly】795.区间子数组个数

力扣题目链接:https://leetcode.cn/problems/number-of-subarrays-with-bounded-maximum/

给你一个整数数组 nums 和两个整数:leftright 。找出 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

方法一:统计

题目中要找的是“最大元素在[left, right]范围内的子数组”

已知$right \geq left$,因此“最大元素在[left, right]范围内的子数组”的数量,等于“最大元素不超过right的子数组数量” - “最大元素不超过left - 1的子数组数量”

因此,我们只需要实现一个函数,这个函数能够计算出“数组a中最大元素不超过b的子数组的数量”

怎么实现呢?

我们用一个变量来记录“上一个大于b的元素的位置”,当再次遇到“大于b的元素”时,二者之间的数组的所有非空子数组都是要找的数组。

假设两个“大于b的元素”之间有$k$个元素,那么这$k$个元素组成的非空子数组的个数就是$k \times (k + 1) / 2$

问题解决。

  • 时间复杂度$O(n)$
  • 空间复杂度$O(1)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
private:
int noMoreThan(vector<int>& a, int b) { // a中的 “所有元素都不大于b 的子数组的个数”
int ans = 0;
int lastLoc = -1;
int n = a.size();
for (int i = 0; i <= n; i++) {
if (i == n || a[i] > b) {
ans += (long long)(i - lastLoc - 1) * (i - lastLoc) / 2;
lastLoc = i;
}
}
return ans;
}
public:
int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
return noMoreThan(nums, right) - noMoreThan(nums, left - 1);
}
};

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/128021990


795.区间子数组个数
https://blog.letmefly.xyz/2022/11/24/LeetCode 0795.区间子数组个数/
作者
Tisfy
发布于
2022年11月24日
许可协议