开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
刷题的日常-2022年11月24号
一天一题,保持脑子清爽
区间子数组个数
来自leetcode的 795 题,题意如下:
给你一个整数数组 nums 和两个整数:left 及 right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。
生成的测试用例保证结果符合 32-bit 整数范围。
示例1:
输入: nums = [2,1,4,3], left = 2, right = 3
输出: 3
解释: 满足条件的三个子数组:[2], [2, 1], [3]
理解题意
通过题意,我们可以将信息整理如下:
- 题目给出一个数组 和 一个范围
- 要求找出最大值在范围内的子数组的数量
做题思路
看题目脑子里的想法是单调栈去做,然后发现边缘条件过多就放弃了,然后看了题解 (*^_^*)。
根据题意,我们要找的范围是出现大于等于 left 并且 小于等于 right,而且没有出现大于right的子数组。
我们先找到第一个大于right的索引位置作为起始点。然后往后扫描,如果出现过满足条件的最大值,那么以当前索引为结束的位置,满足条件的子数组个数就是 最后一个满足条件的索引 减去 上一个大于right的索引位置。步骤如下:
- 开辟左右边界,和一个结果进行记录
- 循环数组元素
- 如果满足条件,将右边界更新为当前索引
- 如果大于
right,则将左边界更新为当前位置,右边界重置为-1 - 最后判断是否存在满足条件的右边界,存在将左右边界的差值加上去
- 返回最终的统计结果
代码实现
代码实现如下,因为只需要扫描一次,所以时间复杂度为O(n),n为数组长度:
public class Solution {
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
int res = 0, l = -1, r = -1, num;
for (int i = 0; i < nums.length; i++) {
num = nums[i];
if (num >= left && num <= right) {
r = i;
} else if (num > right) {
l = i;
r = -1;
}
if (r != -1) {
res += r - l;
}
}
return res;
}
}