Skip to content

Commit 54ec757

Browse files
committed
feat: add solutions to lc problem: No.0795
No.0795.Number of Subarrays with Bounded Maximum
1 parent b21e286 commit 54ec757

File tree

6 files changed

+187
-112
lines changed

6 files changed

+187
-112
lines changed

solution/0700-0799/0795.Number of Subarrays with Bounded Maximum/README.md

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,29 @@
4141

4242
<!-- 这里可写通用的实现逻辑 -->
4343

44-
**方法一:单调栈**
44+
**方法一:区间计数**
4545

46-
我们可以枚举数组中每个元素作为子数组的最大值,然后统计以该元素为最大值的子数组的个数。问题转化为求出每个元素 $nums[i]$ 左侧第一个大于该元素的下标 $l[i]$,右侧第一个大于等于该元素的下标 $r[i]$,则以该元素为最大值的子数组的个数为 $(i - l[i]) \times (r[i] - i)$
46+
题目要我们统计数组 `nums` 中,最大值在区间 $[left, right]$ 范围内的子数组个数
4747

48-
我们可以使用单调栈求出 $l[i]$ 和 $r[i]$。
48+
对于区间 $[left,..right]$ 问题,我们可以考虑将其转换为 $[0,..right]$ 然后再减去 $[0,..left-1]$ 的问题,即:
49+
50+
$$
51+
ans = \sum_{i=0}^{right} ans_i - \sum_{i=0}^{left-1} ans_i
52+
$$
53+
54+
对于本题,我们设计一个函数 $f(x)$,表示数组 `nums` 中,最大值不超过 $x$ 的子数组个数。那么答案为 $f(right) - f(left-1)$。函数 $f(x)$ 的执行逻辑如下:
55+
56+
- 用变量 $cnt$ 记录最大值不超过 $x$ 的子数组的个数,用 $t$ 记录当前子数组的长度。
57+
- 遍历数组 `nums`,对于每个元素 $nums[i]$,如果 $nums[i] \leq x$,则当前子数组的长度加一,即 $t=t+1$,否则当前子数组的长度重置为 0,即 $t=0$。然后将当前子数组的长度加到 $cnt$ 中,即 $cnt = cnt + t$。
58+
- 遍历结束,将 $cnt$ 返回即可。
59+
60+
时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为数组 `nums` 的长度。
61+
62+
**方法二:单调栈 + 枚举元素计算贡献**
63+
64+
我们还可以枚举数组中每个元素 $nums[i]$ 作为子数组的最大值,然后统计以该元素为最大值的子数组的个数。问题转化为求出每个元素 $nums[i]$ 左侧第一个大于该元素的下标 $l[i]$,右侧第一个大于等于该元素的下标 $r[i]$,则以该元素为最大值的子数组的个数为 $(i - l[i]) \times (r[i] - i)$。
65+
66+
我们可以使用单调栈方便地求出 $l[i]$ 和 $r[i]$。
4967

5068
时间复杂度 $O(n)$,空间复杂度 $O(n)$。
5169

@@ -57,6 +75,19 @@
5775

5876
<!-- 这里可写当前语言的特殊实现逻辑 -->
5977

78+
```python
79+
class Solution:
80+
def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
81+
def f(x):
82+
cnt = t = 0
83+
for v in nums:
84+
t = 0 if v > x else t + 1
85+
cnt += t
86+
return cnt
87+
88+
return f(right) - f(left - 1)
89+
```
90+
6091
```python
6192
class Solution:
6293
def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
@@ -83,6 +114,23 @@ class Solution:
83114

84115
<!-- 这里可写当前语言的特殊实现逻辑 -->
85116

117+
```java
118+
class Solution {
119+
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
120+
return f(nums, right) - f(nums, left - 1);
121+
}
122+
123+
private int f(int[] nums, int x) {
124+
int cnt = 0, t = 0;
125+
for (int v : nums) {
126+
t = v > x ? 0 : t + 1;
127+
cnt += t;
128+
}
129+
return cnt;
130+
}
131+
}
132+
```
133+
86134
```java
87135
class Solution {
88136
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
@@ -126,6 +174,23 @@ class Solution {
126174

127175
### **C++**
128176

177+
```cpp
178+
class Solution {
179+
public:
180+
int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
181+
auto f = [&](int x) {
182+
int cnt = 0, t = 0;
183+
for (int& v : nums) {
184+
t = v > x ? 0 : t + 1;
185+
cnt += t;
186+
}
187+
return cnt;
188+
};
189+
return f(right) - f(left -1);
190+
}
191+
};
192+
```
193+
129194
```cpp
130195
class Solution {
131196
public:
@@ -160,6 +225,23 @@ public:
160225

161226
### **Go**
162227

228+
```go
229+
func numSubarrayBoundedMax(nums []int, left int, right int) int {
230+
f := func(x int) (cnt int) {
231+
t := 0
232+
for _, v := range nums {
233+
t++
234+
if v > x {
235+
t = 0
236+
}
237+
cnt += t
238+
}
239+
return
240+
}
241+
return f(right) - f(left-1)
242+
}
243+
```
244+
163245
```go
164246
func numSubarrayBoundedMax(nums []int, left int, right int) (ans int) {
165247
n := len(nums)

solution/0700-0799/0795.Number of Subarrays with Bounded Maximum/README_EN.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@
3939

4040
### **Python3**
4141

42+
```python
43+
class Solution:
44+
def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
45+
def f(x):
46+
cnt = t = 0
47+
for v in nums:
48+
t = 0 if v > x else t + 1
49+
cnt += t
50+
return cnt
51+
52+
return f(right) - f(left - 1)
53+
```
54+
4255
```python
4356
class Solution:
4457
def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
@@ -63,6 +76,23 @@ class Solution:
6376

6477
### **Java**
6578

79+
```java
80+
class Solution {
81+
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
82+
return f(nums, right) - f(nums, left - 1);
83+
}
84+
85+
private int f(int[] nums, int x) {
86+
int cnt = 0, t = 0;
87+
for (int v : nums) {
88+
t = v > x ? 0 : t + 1;
89+
cnt += t;
90+
}
91+
return cnt;
92+
}
93+
}
94+
```
95+
6696
```java
6797
class Solution {
6898
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
@@ -106,6 +136,23 @@ class Solution {
106136

107137
### **C++**
108138

139+
```cpp
140+
class Solution {
141+
public:
142+
int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
143+
auto f = [&](int x) {
144+
int cnt = 0, t = 0;
145+
for (int& v : nums) {
146+
t = v > x ? 0 : t + 1;
147+
cnt += t;
148+
}
149+
return cnt;
150+
};
151+
return f(right) - f(left -1);
152+
}
153+
};
154+
```
155+
109156
```cpp
110157
class Solution {
111158
public:
@@ -140,6 +187,23 @@ public:
140187

141188
### **Go**
142189

190+
```go
191+
func numSubarrayBoundedMax(nums []int, left int, right int) int {
192+
f := func(x int) (cnt int) {
193+
t := 0
194+
for _, v := range nums {
195+
t++
196+
if v > x {
197+
t = 0
198+
}
199+
cnt += t
200+
}
201+
return
202+
}
203+
return f(right) - f(left-1)
204+
}
205+
```
206+
143207
```go
144208
func numSubarrayBoundedMax(nums []int, left int, right int) (ans int) {
145209
n := len(nums)
Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,14 @@
11
class Solution {
22
public:
33
int numSubarrayBoundedMax(vector<int>& nums, int left, int right) {
4-
int n = nums.size();
5-
vector<int> l(n, -1);
6-
vector<int> r(n, n);
7-
stack<int> stk;
8-
for (int i = 0; i < n; ++i) {
9-
int v = nums[i];
10-
while (!stk.empty() && nums[stk.top()] <= v) stk.pop();
11-
if (!stk.empty()) l[i] = stk.top();
12-
stk.push(i);
13-
}
14-
stk = stack<int>();
15-
for (int i = n - 1; ~i; --i) {
16-
int v = nums[i];
17-
while (!stk.empty() && nums[stk.top()] < v) stk.pop();
18-
if (!stk.empty()) r[i] = stk.top();
19-
stk.push(i);
20-
}
21-
int ans = 0;
22-
for (int i = 0; i < n; ++i) {
23-
if (left <= nums[i] && nums[i] <= right) {
24-
ans += (i - l[i]) * (r[i] - i);
4+
auto f = [&](int x) {
5+
int cnt = 0, t = 0;
6+
for (int& v : nums) {
7+
t = v > x ? 0 : t + 1;
8+
cnt += t;
259
}
26-
}
27-
return ans;
10+
return cnt;
11+
};
12+
return f(right) - f(left -1);
2813
}
2914
};
Lines changed: 13 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,14 @@
1-
func numSubarrayBoundedMax(nums []int, left int, right int) (ans int) {
2-
n := len(nums)
3-
l := make([]int, n)
4-
r := make([]int, n)
5-
for i := range l {
6-
l[i], r[i] = -1, n
7-
}
8-
stk := []int{}
9-
for i, v := range nums {
10-
for len(stk) > 0 && nums[stk[len(stk)-1]] <= v {
11-
stk = stk[:len(stk)-1]
12-
}
13-
if len(stk) > 0 {
14-
l[i] = stk[len(stk)-1]
15-
}
16-
stk = append(stk, i)
17-
}
18-
stk = []int{}
19-
for i := n - 1; i >= 0; i-- {
20-
v := nums[i]
21-
for len(stk) > 0 && nums[stk[len(stk)-1]] < v {
22-
stk = stk[:len(stk)-1]
23-
}
24-
if len(stk) > 0 {
25-
r[i] = stk[len(stk)-1]
26-
}
27-
stk = append(stk, i)
28-
}
29-
for i, v := range nums {
30-
if left <= v && v <= right {
31-
ans += (i - l[i]) * (r[i] - i)
32-
}
33-
}
34-
return
1+
func numSubarrayBoundedMax(nums []int, left int, right int) int {
2+
f := func(x int) (cnt int) {
3+
t := 0
4+
for _, v := range nums {
5+
t++
6+
if v > x {
7+
t = 0
8+
}
9+
cnt += t
10+
}
11+
return
12+
}
13+
return f(right) - f(left-1)
3514
}
Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,14 @@
11
class Solution {
22
public int numSubarrayBoundedMax(int[] nums, int left, int right) {
3-
int n = nums.length;
4-
int[] l = new int[n];
5-
int[] r = new int[n];
6-
Arrays.fill(l, -1);
7-
Arrays.fill(r, n);
8-
Deque<Integer> stk = new ArrayDeque<>();
9-
for (int i = 0; i < n; ++i) {
10-
int v = nums[i];
11-
while (!stk.isEmpty() && nums[stk.peek()] <= v) {
12-
stk.pop();
13-
}
14-
if (!stk.isEmpty()) {
15-
l[i] = stk.peek();
16-
}
17-
stk.push(i);
18-
}
19-
stk.clear();
20-
for (int i = n - 1; i >= 0; --i) {
21-
int v = nums[i];
22-
while (!stk.isEmpty() && nums[stk.peek()] < v) {
23-
stk.pop();
24-
}
25-
if (!stk.isEmpty()) {
26-
r[i] = stk.peek();
27-
}
28-
stk.push(i);
29-
}
30-
int ans = 0;
31-
for (int i = 0; i < n; ++i) {
32-
if (left <= nums[i] && nums[i] <= right) {
33-
ans += (i - l[i]) * (r[i] - i);
34-
}
3+
return f(nums, right) - f(nums, left - 1);
4+
}
5+
6+
private int f(int[] nums, int x) {
7+
int cnt = 0, t = 0;
8+
for (int v : nums) {
9+
t = v > x ? 0 : t + 1;
10+
cnt += t;
3511
}
36-
return ans;
12+
return cnt;
3713
}
3814
}
Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
class Solution:
22
def numSubarrayBoundedMax(self, nums: List[int], left: int, right: int) -> int:
3-
n = len(nums)
4-
l, r = [-1] * n, [n] * n
5-
stk = []
6-
for i, v in enumerate(nums):
7-
while stk and nums[stk[-1]] <= v:
8-
stk.pop()
9-
if stk:
10-
l[i] = stk[-1]
11-
stk.append(i)
12-
stk = []
13-
for i in range(n - 1, -1, -1):
14-
while stk and nums[stk[-1]] < nums[i]:
15-
stk.pop()
16-
if stk:
17-
r[i] = stk[-1]
18-
stk.append(i)
19-
return sum(
20-
(i - l[i]) * (r[i] - i) for i, v in enumerate(nums) if left <= v <= right
21-
)
3+
def f(x):
4+
cnt = t = 0
5+
for v in nums:
6+
t = 0 if v > x else t + 1
7+
cnt += t
8+
return cnt
9+
10+
return f(right) - f(left - 1)

0 commit comments

Comments
 (0)