单调队列

[Algo] 单调队列

1. 滑动窗口最大值

// 1. 滑动窗口最大值
// https://leetcode.cn/problems/sliding-window-maximum/description/
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    deque<int> dq;
    vector<int> result;
    for (int i = 0; i < k; i++)
    {
        while (!dq.empty() && nums[dq.back()] <= nums[i]) dq.pop_back();
        dq.push_back(i);
    }
    result.push_back(nums[dq.front()]);
    int r = k;
    while (r <= nums.size() - 1)
    {
        while (!dq.empty() && nums[dq.back()] <= nums[r]) dq.pop_back();
        dq.push_back(r);
        if (dq.front() == r - k) dq.pop_front();
        result.push_back(nums[dq.front()]);
        r++;
    }
    return result;
}

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

// 2. 绝对差不超过限制的最长连续子数组
// https://leetcode.cn/problems/longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit/
int longestSubarray(vector<int>& nums, int limit) {
    deque<int> dq_max, dq_min;
    dq_max.push_back(0);
    dq_min.push_back(0);
    int ans = 1;
    for (int l = 0, r = 1; r < nums.size(); l++)
    {
        if (l == r)
        {
            dq_max.push_back(l);
            dq_min.push_back(l);
            r++;
        }
        int cur_max = nums[dq_max.front()];
        int cur_min = nums[dq_min.front()];
        while (r < nums.size() && nums[r] >= cur_max - limit && nums[r] <= cur_min + limit)
        {
            while (!dq_max.empty() && nums[dq_max.back()] <= nums[r]) dq_max.pop_back();
            dq_max.push_back(r);
            while (!dq_min.empty() && nums[dq_min.back()] >= nums[r]) dq_min.pop_back();
            dq_min.push_back(r);
            cur_max = nums[dq_max.front()];
            cur_min = nums[dq_min.front()];
            r++;
        }
        ans = max(ans, r - l);
        if (dq_max.front() == l) dq_max.pop_front();
        if (dq_min.front() == l) dq_min.pop_front();
    }
    return ans;
}

3. 和至少为K的最短子数组

// 3. 和至少为K的最短子数组
// https://leetcode.cn/problems/shortest-subarray-with-sum-at-least-k/description/
int shortestSubarray(vector<int>& nums, int k) {
    vector<int> sum;
    sum.resize(nums.size() + 1);
    for (int i = 1; i < sum.size(); i++) sum[i] = sum[i - 1] + nums[i - 1];
    deque<int> dq;
    dq.push_back(0);
    int ans = INT32_MAX;
    for (int i = 1; i < sum.size(); i++)
    {
        while (!dq.empty() && sum[i] - sum[dq.front()] >= k)
        {
            ans = min(ans, i - dq.front());
            dq.pop_front();
        }
        while (!dq.empty() && sum[dq.back()] >= sum[i]) dq.pop_back();
        dq.push_back(i);
    }
    return ans == INT32_MAX ? -1 : ans;
}
posted @ 2025-01-06 09:33  yaoguyuan  阅读(11)  评论(0)    收藏  举报