题目
-
给一个 int 组成的数组
-
返回满足以下条件的子数组的个数
- 子数组内的任意两个数字的差小于等于 2
思路
- 滑动窗口 + 单调队列
- 定义一个严格单调递增的队列,记录区间 min
- 定义一个严格单调递减的队列,记录区间 max
- 固定 left,滑动 right,找到满足要求的子数组,此时可以满足条件的子数组个数为 right - left + 1
- 遍历固定 left 的起始位置,进行统计
代码
class Solution {
public:
long long continuousSubarrays(vector<int>& nums) {
int n = nums.size();
long long ans = 0;
deque<pair<int, int>> min_dq, max_dq;
min_dq.push_back(make_pair(nums[0], 0));
max_dq.push_back(make_pair(nums[0], 0));
int j = 0;
for (int i = 0; i < n; i++) {
while (min_dq.front().second < i) {
min_dq.pop_front();
}
int mi_num = min_dq.front().first;
while (max_dq.front().second < i) {
max_dq.pop_front();
}
int ma_num = max_dq.front().first;
if (j == n) {
if (ma_num - mi_num <= 2) {
ans += j - i;
}
continue;
}
while (ma_num - mi_num <= 2) {
j++;
if (j == n) break;
// update min dq
while (min_dq.empty() == false && min_dq.back().first >= nums[j]) min_dq.pop_back();
min_dq.push_back(make_pair(nums[j], j));
// update max dq
while (max_dq.empty() == false && max_dq.back().first <= nums[j]) max_dq.pop_back();
max_dq.push_back(make_pair(nums[j], j));
mi_num = min_dq.front().first;
ma_num = max_dq.front().first;
}
ans += j - i;
}
return ans;
}
};