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

思路1 滑动窗口+multiset的 rbegin()begin()

  1. 滑动窗口(当limit超出之后,再增加长度是没有意义的,因为最大值最小值已经确定了
  2. 如何实现滑动窗口?——判断左指针何时右移,确定右指针界限
  3. 如何返回最大值和最小值?——C++自带的multiset中的rbegin()和begin()

代码1

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        multiset<int> s;//用于返回最大最小值 底层为红黑树
        int n = nums.size();
        int left = 0, right = 0;
        int ans = 0;
        while (right < n) {
            s.insert(nums[right]);
            //差值超过limit进行s删除 并且滑动窗口左指针向右移
            while (*s.rbegin() - *s.begin() > limit) 
                s.erase(s.find(nums[left++]));
            //获取最大值
            ret = max(ret, right - left + 1);
            right++;
        }
        return ans;
    }
};

思路2 滑动窗口+双单调队列

  1. 题目需要的最大值和最小值,可以双单调队列实现
  2. MAX永远为大元素让步,MIN永远为小元素让步,保持top的极值性
例如8 2 4 7 9MAX为8 MIN为82 进入后 MAX为8 2 MIN为24 进入后 MAX为8 4 MIN为2 47 进入后 MAX为8 7 MIN为2 4 79 进入后 MAX为9   MIN为2 4 7 9

代码2

class Solution {
public:
    int longestSubarray(vector<int>& nums, int limit) {
        deque<int> queMax, queMin;
        int left = 0, right = 0;
        int ret = 0;
        while (right < nums.size()) {
            //大堆的尾巴小于当前值 不断弹出 保持top为最大
            while (!queMax.empty() && queMax.back() < nums[right]) 
                queMax.pop_back();
            queMax.push_back(nums[right]);
            //小堆的尾巴大于当前值 不断弹出  保持top为最小
            while (!queMin.empty() && queMin.back() > nums[right]) 
                queMin.pop_back();
            queMin.push_back(nums[right]);
            //超过limit 弹出left left++
            while (!queMax.empty() && !queMin.empty() && queMax.front() - queMin.front() > limit) {
                if (nums[left] == queMin.front()) 
                    queMin.pop_front();
                if (nums[left] == queMax.front()) 
                    queMax.pop_front();
                left++;
            }
            ret = max(ret, right - left + 1);
            right++;
        }
        return ret;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值