795. Number of Subarrays with Bounded Maximum
795. Number of Subarrays with Bounded Maximum
Given an integer array nums
and two integers left
and right
, return the number of contiguous non-empty subarrays such that the value of the maximum array element in that subarray is in the range [left, right]
.
The test cases are generated so that the answer will fit in a 32-bit integer.
Example 1:
Input: nums = [2,1,4,3], left = 2, right = 3
Output: 3
Explanation: There are three subarrays that meet the requirements: [2], [2, 1], [3].
Example 2:
Input: nums = [2,9,2,5,6], left = 2, right = 8
Output: 7
Constraints:
1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= left <= right <= 109
My Solutions:
方法1:和560类似,可以用暴力解法,遍历每一个subarray。有些直接超出范围的可以省略
public int numSubarrayBoundedMax(int[] nums, int L, int R) {
int N = nums.size();
int res = 0;
for (int i = 0; i < N; i++) {
if (nums[i] > R) continue; // 超出范围,跳过
int curMax = -1; // 也可以用最小数
for (int j = i; j < N; j++) {
curMax = max(curMax, A[j]);
if (curMax > R) break;
if (curMax >= L) res++;
}
}
return res;
}
方法2:
看数组[2, 1, 4, 3]的最大值在[-∞, 4]范围内的子数组的个数。
遍历到2时,只有一个子数组[2]
遍历到1时,有三个子数组,[2], [1], [2,1]
遍历到4时,有六个子数组,[2], [1], [4], [2,1], [1,4], [2,1,4]
遍历到3时,有十个子数组,[2], [1], [4], [3],[2,1], [1,4], [4,3],[2,1,4],[1,4,3],[2,1,4,3]
如果长度为n的数组的最大值在范围[-∞, x]内的话,其所有子数组都是符合题意的,而长度为n的数组共有n(n+1)/2个子数组,是等差数列的求和公式。所以在遍历数组的时候,如果当前数组小于等于x,则cur自增1,然后将cur加到结果res中;如果大于x,则cur重置为0。这样可以正确求出最大值在[-∞, x]范围内的子数组的个数。
只需要用最大值在[-∞, R]范围内的子数组的个数,减去最大值在[-∞, L-1]范围内的子数组的个数,即可得到最大值在[L, R]范围内的子数组的个数
public int numSubarrayBoundedMax(int[] A, int L, int R) {
return count(A, R) - count(A, L - 1);
}
public int count(int[] A, int bound) {
int res = 0, cur = 0;
for (int x : A) {
cur = (x <= bound) ? cur + 1 : 0;
res += cur;
}
return res;
}
方法3:理念和方法2类似
使用left和right来分别标记子数组的左右边界,使得其最大值在范围[L,R]内
当A[i]大于等于L时,right赋值为当前位置i,那么每次res加上right - left,随着right的不停自增1,每次加上的right - left,实际上也是一个等差数列
当A[i]大于R的时候,left = i,right=i,那么right - left为0,相当于上面的cur重置为0的操作
public int numSubarrayBoundedMax(int A, int L, int R) {
int res = 0, left = -1, right = -1;
for (int i = 0; i < A.size(); ++i) {
if (A[i] > R) {
left = right = i;
continue;
}
if (A[i] >= L) right = i;
res += right - left;
}
return res;
}
Last updated