1438. 绝对差不超过限制的最长连续子数组

这个题目看到要找一个最长连续的子数组,就可以知道肯定是要用滑动窗口的,但是我们不能简单的套用滑动窗口的模板,题目的一个限制是,窗口内的最大元素减最小元素的差值要小于等于limit。如果我们每次都对窗口求一次最大最小值,时间复杂度就$O(N)\times k$,k是窗口的长度,在这个题目是需要超时的。既然每次都需要最大最小值。和我之前写这篇文章是类似的 leetcode-239. 滑动窗口最大值维护一个单调队列,我们就能在$O(1)$的时间复杂度查询最值,只不过这个题目即需要最大值,又需要最小值,我们需要维护两个单调队列。

from collections import deque

class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        max_dq = deque()
        min_dq = deque()
        res = 0
        l = 0
        for i, num in enumerate(nums):
            while max_dq and num >= nums[max_dq[-1]]:
                max_dq.pop()
            max_dq.append(i)
            while min_dq and num <= nums[min_dq[-1]]:
                min_dq.pop()
            min_dq.append(i)
            while nums[max_dq[0]] - nums[min_dq[0]] > limit:
                if max_dq[0] == l:
                    max_dq.popleft()
                if min_dq[0] == l:
                    min_dq.popleft()
                l += 1
            res = max(res, i - l + 1)
        return res

239题缩小窗口是可以用if的,因为是定长的,每次最多就缩一次,但是这里一定是需要用while的,有可能移除了一个元素之后,依然是不符合条件需要继续缩小的。缩小完之后的窗口一定是符合条件的,更新答案就可以了。