【Leetcode】2444. Count Subarrays With Fixed Bounds

题目地址:

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:ki(ak<mak>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:ki(ak<mak>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:kiak=m},v=max{k:kiak=M},那么只需要 j ≤ min ⁡ { u , v } j\le \min\{u,v\} jmin{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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值