Leetcode1438 Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit (滑动窗口+双单调队列)

最长连续子数组:绝对差小于等于限制的算法
  1. Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
    Medium
    Given an array of integers nums and an integer limit, return the size of the longest non-empty subarray such that the absolute difference between any two elements of this subarray is less than or equal to limit.

Example 1:

Input: nums = [8,2,4,7], limit = 4
Output: 2
Explanation: All subarrays are:
[8] with maximum absolute diff |8-8| = 0 <= 4.
[8,2] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4] with maximum absolute diff |8-2| = 6 > 4.
[8,2,4,7] with maximum absolute diff |8-2| = 6 > 4.
[2] with maximum absolute diff |2-2| = 0 <= 4.
[2,4] with maximum absolute diff |2-4| = 2 <= 4.
[2,4,7] with maximum absolute diff |2-7| = 5 > 4.
[4] with maximum absolute diff |4-4| = 0 <= 4.
[4,7] with maximum absolute diff |4-7| = 3 <= 4.
[7] with maximum absolute diff |7-7| = 0 <= 4.
Therefore, the size of the longest subarray is 2.
Example 2:

Input: nums = [10,1,2,4,7,2], limit = 5
Output: 4
Explanation: The subarray [2,4,7,2] is the longest since the maximum absolute diff is |2-7| = 5 <= 5.
Example 3:

Input: nums = [4,2,2,2,4,4,2,2], limit = 0
Output: 3

Constraints:

1 <= nums.length <= 105
1 <= nums[i] <= 109
0 <= limit <= 109

解法1:这题我觉得不简单。
要维护一个滑动窗口和两个单调队列(一个维护窗口最大值,一个维护窗口最小值)。
注意:

  1. 这两个单调队列(maxQ和minQ)里面的值不一样,但窗口的边界(left, right)是一致的。也就是说,滑动窗口就一个,里面的最小值就是minQ的最小值(front),里面的最大值就是maxQ的最大值(front)。
  2. maxQ和minQ的back就是滑动窗口的右边界(right),注意因为right每次加1,所以maxQ和minQ的back可能是right-1。
  3. maxQ和minQ的front可能会比滑动窗口的左边界(left)大一些,当然也可能等于left,但不会小于left。也就是说,滑动窗口的left, right边界会完全cover住maxQ和minQ。
  4. minQ是单调递增队列(从front到back单调递增),maxQ是单调递减队列(从front到back单调递减)。minQ的front就是滑动窗口的最小值,maxQ的front就是滑动窗口的最大值。
  5. 每次进nums[right],maxQ和minQ根据各自的back来决定要不要pop back。
  6. 当maxQ的front - minQ的front 对应的值的difference > limit的时候,我们就要决定移动left。直到这两者的difference < limit。注意:maxQ的front和minQ的front有可能>left, 这时候我们不能pop_front,因为它们必须保留在滑动窗口内。只有front<=left的时候,才能安全pop_front()。
class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        int n = nums.size();
        deque<int> minQ, maxQ;
        int left = 0, right = 0, res = 0;
        while (right < n) {
            while(minQ.size() > 0 && nums[minQ.back()] > nums[right]) {
                minQ.pop_back();
            }
            minQ.push_back(right);
            
            while(maxQ.size() > 0 && nums[maxQ.back()] < nums[right]) {
                maxQ.pop_back();
            }
            maxQ.push_back(right);
            right++;
           
            while (nums[maxQ.front()] - nums[minQ.front()] > limit) {
                if (maxQ.front() <= left) maxQ.pop_front();
                if (minQ.front() <= left) minQ.pop_front();
                left++;
            }
            res = max(res, right - left);
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值