题目地址:

https://leetcode.com/problems/number-of-subarrays-that-match-a-pattern-ii/description/

给定一个长 n n n数组 a a a,和一个只含 − 1 , 0 , 1 -1,0,1 1,0,1的长 m m m数组 p p p,题目保证 n ≥ 2 , m ≥ 1 n\ge 2, m\ge 1 n2,m1。如果存在 a a a的一个长 m + 1 m+1 m+1的子数组,使得 a [ i ] < a [ i + 1 ] , a [ i ] = a [ i + 1 ] , a [ i ] > a [ i + 1 ] a[i]<a[i+1],a[i]=a[i+1],a[i]>a[i+1] a[i]<a[i+1],a[i]=a[i+1],a[i]>a[i+1]分别等价于 p [ i ] = 1 , 0 , − 1 p[i]=1,0,-1 p[i]=1,0,1,就说这段子数组满足 p p p的模式。问 a a a有多少个子数组满足 p p p模式。

先将 a a a做一个变换,变换为 s s s数组,使得 s [ i ] = sgn ⁡ ( a [ i + 1 ] − a [ i ] ) s[i]=\operatorname{sgn} (a[i+1]-a[i]) s[i]=sgn(a[i+1]a[i]),问题转化为问 s s s中含子数组 p p p多少次,可以用KMP算法来做。代码如下:

class Solution {
public:
  int countMatchingSubarrays(vector<int> &a, vector<int> &p) {
    int n = a.size(), m = p.size();
    if (n - 1 < m) return 0;
    vector<int> s(n);
    for (int i = 1; i < n; i++)
      s[i] = (a[i] > a[i - 1]) - (a[i] < a[i - 1]);

    p.insert(p.begin(), 0);
    auto ne = [&](auto &p) {
      vector<int> ne(m + 1);
      for (int i = 2, j = 0; i <= m; i++) {
        while (j && p[i] != p[j + 1]) j = ne[j];
        if (p[i] == p[j + 1]) j++;
        ne[i] = j;
      }
      return ne;
    }(p);

    int res = 0;
    for (int i = 1, j = 0; i <= n - 1; i++) {
      while (j && s[i] != p[j + 1]) j = ne[j];
      if (s[i] == p[j + 1]) j++;
      if (j == m) {
        res++;
        j = ne[j];
      }
    }

    return res;
  }
};

时间复杂度 O ( n + m ) O(n+m) O(n+m),空间 O ( m ) O(m) O(m)

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新

更多推荐