题目地址:
https://leetcode.com/problems/count-subarrays-with-fixed-bounds/description/
给定一个长 n n n数组 a a a,再给定两个数 m m m和 M M M且 m < M m<M m<M。问最小值恰好为 m m m并且最大值恰好为 M M M的子数组的个数。
枚举 i i i,我们想知道以 a [ i ] a[i] a[i]为右端点的数组满足条件的有多少个,设 a [ j : i ] a[j:i] a[j:i]满足条件,我们其实是在考虑 j j j的取值个数。显然 j > max { k : k ≤ i ∧ ( a k < m ∨ a k > M ) } j> \max \{k:k\le i \land ( a_k<m\lor a_k> M)\} j>max{k:k≤i∧(ak<m∨ak>M)},也就是说,如果令 l = max { k : k ≤ i ∧ ( a k < m ∨ a k > M ) } l=\max \{k:k\le i \land ( a_k<m\lor a_k> M)\} l=max{k:k≤i∧(ak<m∨ak>M)},那么 l l l就是 j j j向左最远能延伸到的地方,而此时 a [ l + 1 : i ] a[l+1:i] a[l+1:i]的数都是范围在 [ m , M ] [m,M] [m,M]的,从而我们只需要保证 m , M m,M m,M这两个数都在区间里就行了。我们找到 u = max { k : k ≤ i ∧ a k = m } , v = max { k : k ≤ i ∧ a k = M } u=\max\{k:k\le i \land a_k=m\},v=\max\{k:k\le i\land a_k=M\} u=max{k:k≤i∧ak=m},v=max{k:k≤i∧ak=M},那么只需要 j ≤ min { u , v } j\le \min\{u,v\} j≤min{u,v},就能保证 a [ j : i ] a[j:i] a[j:i]的最小值和最大值恰好是 m m m和 M M M。所以, j j j的范围就是 [ l + 1 , min { u , v } ] [l+1,\min\{u,v\}] [l+1,min{u,v}]。对于每个 i i i,对 j j j的范围长度求和即可。代码如下:
class Solution {
public:
using ll = long long;
ll countSubarrays(vector<int>& a, int minK, int maxK) {
ll res = 0;
int last_min = -1, last_max = -1, l_bound = -1;
for (int i = 0; i < a.size(); i++) {
if (a[i] < minK || a[i] > maxK) {
l_bound = i;
last_min = last_max = -1;
} else {
if (a[i] == minK) last_min = i;
if (a[i] == maxK) last_max = i;
if (min(last_min, last_max) > l_bound)
res += min(last_min, last_max) - l_bound;
}
}
return res;
}
};
时间复杂度 O ( n ) O(n) O(n),空间 O ( 1 ) O(1) O(1)。