Problem: 1438. 绝对差不超过限制的最长连续子数组
文章目录
思路
这个问题可以使用滑动窗口和两个单调队列来解决。一个单调队列用来维护窗口内的最大值,另一个单调队列用来维护窗口内的最小值。我们从左到右遍历数组,对于每个元素,我们首先检查如果将这个元素加入窗口后,窗口内的最大值和最小值的差是否超过限制。如果超过限制,我们就移动窗口的左边界,直到窗口内的最大值和最小值的差不超过限制为止。
解题方法
我们首先初始化两个空的单调队列和一个结果变量。然后,我们从左到右遍历输入数组,对于每个元素,我们首先检查如果将这个元素加入窗口后,窗口内的最大值和最小值的差是否超过限制。如果超过限制,我们就移动窗口的左边界,直到窗口内的最大值和最小值的差不超过限制为止。然后,我们将当前元素加入到两个单调队列中,并更新结果变量。
复杂度
时间复杂度:
O ( n ) O(n) O(n),其中n是数组的长度。每个元素只会被加入到单调队列一次,所以时间复杂度是线性的。
空间复杂度:
O ( n ) O(n) O(n),在最坏的情况下,两个单调队列中可能会包含所有的元素,所以空间复杂度是线性的。
Code
java
class Solution {
public static int MAXN = 100010;
public static int[] maxdeque = new int[MAXN];
public static int[] mindeque = new int[MAXN];
public static int maxh, maxt, minh, mint;
public static int[] arr;
public static int longestSubarray(int[] nums, int limit) {
maxh = maxt = minh = mint = 0;
int n = nums.length;
arr = nums;
int ans = 0;
for (int l = 0, r = 0; l < n; l++) {
while (r < n && ok(limit, nums[r])) {
push(r++);
}
ans = Math.max(ans, r - l);
poll(l);
}
return ans;
}
public static void push(int r) {
while(maxh < maxt && arr[maxdeque[maxt - 1]] <= arr[r]) {
maxt--;
}
maxdeque[maxt++] = r;
while(minh < mint && arr[mindeque[mint - 1]] >= arr[r]) {
mint--;
}
mindeque[mint++] = r;
}
public static void poll(int l) {
if(maxh < maxt && maxdeque[maxh] == l) {
maxh++;
}
if(minh < mint && mindeque[minh] == l) {
minh++;
}
}
public static boolean ok(int limit, int number) {
int max = maxh < maxt ? Math.max(arr[maxdeque[maxh]], number) : number;
int min = minh < mint ? Math.min(arr[mindeque[minh]], number) : number;
return max - min <= limit;
}
}