[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 }

 

LeetCode 题目总结

posted @ 2022-11-24 05:55  CNoodle  阅读(43)  评论(0编辑  收藏  举报