一、 题目
![在这里插入图片描述](https://img-blog.csdnimg.cn/e617ec5ab07b4bff8e5e96b502f01083.png)
二、 示例
![在这里插入图片描述](https://img-blog.csdnimg.cn/de32d286be744fb0837e34ccf54271c4.png)
三、 思路与代码
1. 思路:
- 采用滑动窗口算法, 而关于窗口容器采用一个特殊的数据结构, 即multiset;
- 在 C++ 中 multiset 内部元素是有序的,基于红黑树实现。
multiset
可以有重复元素;
- 本题的关键就在于, 如何快速的找到窗口内的最大值与最小值? 利用multiset,
mutiset.rbegin()
返回引用multiset容器最后一个元素(最大值)的反向迭代器, 而multiset.begin()
则是正向迭代器;
- 因为, 只要窗口中最大值与最小值之间的差值都超过了限制值limit, 则说明任意两个数字之间的差都不符合;
- 首先,right指针移动滑动窗口;而当窗口中最大值与最小值之间的差超过了限制limit, 则left指针移动收缩窗口(multiset.erase());
- 更新答案的时机为:窗口中最大值与最小值的差不超过limit时, 更新数据;
- 注意从窗口中移出元素的操作!!!:这里用的是multiset容器(因为题目给出的值可能有重复), 所以在删除的时候不能直接erase, 这样会把所有重复的值都删除掉, 要先windows.find(value):
multiset::find
(是C++ STL中的内置函数,该函数返回指向在多集容器中搜索的元素的lower_bound的迭代器。如果未找到该元素,则迭代器指向该集合中最后一个元素之后的位置;找到后再erase掉, 这样从窗口中移出元素才是正确的;具体见代码解析;
2. 代码:
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
multiset<int> mst;
int left = 0;
int right = 0;
int n_len = nums.size();
int cnt = 0;
while (right < n_len) {
int c = nums[right];
right++;
mst.insert(c);
while (*mst.rbegin() - *mst.begin() > limit) {
int d = nums[left];
left++;
mst.erase(mst.find(d));
}
cnt = max(cnt, right - left);
}
return cnt;
}
};