[LeetCode] 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
区间子数组个数。
给你一个整数数组 nums 和两个整数:left 及 right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。
生成的测试用例保证结果符合 32-bit 整数范围。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/number-of-subarrays-with-bounded-maximum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题属于动态规划类型的题目。题意不难理解,给了一个数字的范围 [left, right] 和一个数组 nums,请你返回满足题意的子数组的个数。注意子数组的定义是最大元素要介于 [left, right] 之间。
这里我们需要创建一个 dp[i] 数组,数组的定义是以 nums[i] 结尾的满足题意的子数组的个数。对于每个 nums[i],
- 如果这个数字在范围内,那么以 nums[i] 结尾的子数组的长度就可以累加 += end - start + 1。
- 如果这个数字小于下界 left,那么我们看一下他之前一个位置上的DP值,即 dp[i - 1],因为当前值小于 left 的时候,他依然可以放在之前的某个子数组的末端,所以以 nums[i] 结尾的子数组的长度 dp[i] = dp[i - 1] + 1
- 如果这个数字大于上界 right,那么他就不可以被接在之前的数组的末端,所以当前位置的 dp 值就只能从 0 开始
时间O(n)
空间O(1)
Java实现
1 class Solution { 2 public int numSubarrayBoundedMax(int[] nums, int left, int right) { 3 // corner case 4 if (left == right) { 5 return 0; 6 } 7 8 // normal case 9 int res = 0; 10 int prev = 0; 11 int start = 0; 12 for (int end = 0; end < nums.length; end++) { 13 if (nums[end] >= left && nums[end] <= right) { 14 // 如果当前数字在范围内,那么以当前数字为结尾的子数组的数量就可以累加(end - start + 1)个 15 // prev记录的相当于是dp[i - 1] 16 res += end - start + 1; 17 prev = end - start + 1; 18 } else if (nums[end] < left) { 19 // 如果当前数字小于下界,当前数字依然可以放到之前有效子数组的末尾,这样prev就用上了 20 // 等于是dp[i] = dp[i - 1], res += dp[i] 21 res += prev; 22 } else { 23 // 如果当前数字大于上界,那么就必须重新计算了 24 start = end + 1; 25 prev = 0; 26 } 27 } 28 return res; 29 } 30 }