题目地址:
给定一个长 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{i−f(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) {
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)。