题目描述:
给你一个整数数组 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 <= 10^5
0 <= nums[i] <= 10^9
0 <= left <= right <= 10^9
解题思路:
若数组nums中所有元素都在范围 [left, right] 内,则满足条件的子数组的个数为:
(length(nums)+1)*length(nums)/2
(注意,虽然题目中说“用例保证结果符合 32-bit 整数范围”,但运行过程中(length(nums)+1)*length(nums)可能会超过整数范围,因此应该先用long类型计算,计算后的结果除以2才能用int类型接收)
先考虑数组nums中大于right的元素,比如 (nums = [2,1,4,3], left = 2, right = 3)其中4大于right,4只要加入到子数组一定会不满足条件,因此大于right的数切割数组,将其分为[2,1]和[3],其中[2,1]可以产生的子数组为3个([2],[1],[2,1]),[3]可以产生一个,总共为4个
再考虑数组小于left的元素,比如 (nums = [2,1,4,3], left = 2, right = 3)其中1小于left,[1]能产生的子数组数量为1
最后用用只考虑大于right的元素产生的子数组个数 减去只考虑小于left的元素产生子数组个数(4-1)为最终值。
代码:
class Solution {
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
ArrayList<Integer> bigArrayList = new ArrayList<>();
ArrayList<Integer> littleArrayList = new ArrayList<>();
for(int i = 0;i<nums.length;i++){
if(nums[i]>right){
bigArrayList.add(i);
}else if(nums[i]<left){
littleArrayList.add(i);
}
}
if (littleArrayList.size()==0&&bigArrayList.size()==0){
return getSum(nums.length);
}
int sum = 0;
for(int j = 0;j<bigArrayList.size();j++){
if(j==0){
sum+=getSum(bigArrayList.get(j)-0);
}
if (j+1==bigArrayList.size()){
sum+=getSum(nums.length-1-bigArrayList.get(j));
}else {
sum+=getSum(bigArrayList.get(j+1)-bigArrayList.get(j)-1);
}
}
int sub = 0;
for(int j = 0;j<littleArrayList.size();j++){
int length = 1;
for (int i = j+1; i < littleArrayList.size(); i++) {
if (littleArrayList.get(i)-littleArrayList.get(j)==1){
length++;
j++;
}
}
sub+=getSum(length);
}
return sum-sub;
}
public static int getSum(int i){
long l = i;
long res = (1+l)*l/2;
return (int)res;
}
}