【Leetcode】1438. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit

题目地址:

https://leetcode.com/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/description/

给定一个长 n n n数组 a a a,再给定一个非负整数 l l l,求最长的极差小于等于 l l l的子数组,返回其长度。

对于任意 i i i,我们找到最左边的 j j j使得 a [ j : i ] a[j:i] a[j:i]的极差小于等于 l l l,令这样的 j = f ( i ) j=f(i) j=f(i)。当 i i i变大的时候, a [ j : i ] a[j:i] a[j:i]的极差不会变小,从而 j j j不会向左回退。我们用两个单调双端队列维护 a [ j : i ] a[j:i] a[j:i]的最大值和最小值的下标,从而也就能得到 a [ j : i ] a[j:i] a[j:i]的极差。当 a [ j : i ] a[j:i] a[j:i]的极差大于 l l l的时候,收缩左端点。那么答案就是 max ⁡ i { i − f ( i ) + 1 } \max_i \{i-f(i)+1\} maxi{if(i)+1}。代码如下:

class Solution {
 public:
  int longestSubarray(vector<int>& a, int l) {
    deque<int> dq_max, dq_min;
    int res = 0;
    for (int i = 0, j = 0; i < a.size(); i++) {
      while (dq_max.size() && a[dq_max.back()] <= a[i]) dq_max.pop_back();
      while (dq_min.size() && a[dq_min.back()] >= a[i]) dq_min.pop_back();
      dq_max.push_back(i);
      dq_min.push_back(i);
      while (a[dq_max.front()] - a[dq_min.front()] > l) {
        j++;
        if (j > dq_max.front()) dq_max.pop_front();
        if (j > dq_min.front()) dq_min.pop_front();
      }

      res = max(res, i - j + 1);
    }
    return res;
  }
};

时空复杂度 O ( n ) O(n) O(n)

当然也可以用一个BBST来维护区间信息。这里维护区间每个数出现的次数。代码如下:

class Solution {
 public:
  int longestSubarray(vector<int>& a, int l) {
    map<int, int> mp;
    int res = 0;
    for (int i = 0, j = 0; i < a.size(); i++) {
      mp[a[i]]++;
      while (mp.rbegin()->first - mp.begin()->first > l) {
        mp[a[j]]--;
        if (!mp[a[j]]) mp.erase(a[j]);
        j++;
      }

      res = max(res, i - j + 1);
    }
    return res;
  }
};

时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),空间 O ( n ) O(n) O(n)

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值