Files
leetcode-master/problems/kamacoder/0122.滑动窗口最大值.md
programmercarl 96f4622dcf 图论更新
2024-06-13 10:29:09 +08:00

3.7 KiB
Raw Blame History

滑动窗口最大值

本题是 代码随想录:滑动窗口最大值 的升级版。

代码随想录:滑动窗口最大值 中详细讲解了如何求解 滑动窗口的最大值。

那么求滑动窗口的最小值原理也是一样的, 大家稍加思考,把优先级队列里的 大于 改成小于 就行了。

求最大值的优先级队列(从大到小)

while (!que.empty() && value > que.back()) {

求最小值的优先级队列(从小到大)

while (!que.empty() && value > que.back()) {

这样在滑动窗口里 最大值最小值都求出来了,遍历一遍找出 差值最大的就好。

至于输入,需要一波字符串处理,比较考察基本功。

CPP代码如下

#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <deque>
using namespace std;
class MyBigQueue { //单调队列(从大到小)
public:
    deque<int> que; // 使用deque来实现单调队列
    // 每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
    // 同时pop之前判断队列当前是否为空。
    void pop(int value) {
        if (!que.empty() && value == que.front()) {
            que.pop_front();
        }
    }
    // 如果push的数值大于入口元素的数值那么就将队列后端的数值弹出直到push的数值小于等于队列入口元素的数值为止。
    // 这样就保持了队列里的数值是单调从大到小的了。
    void push(int value) {
        while (!que.empty() && value > que.back()) {
            que.pop_back();
        }
        que.push_back(value);

    }
    // 查询当前队列里的最大值 直接返回队列前端也就是front就可以了。
    int front() {
        return que.front();
    }
};

class MySmallQueue { //单调队列(从小到大)
public:
    deque<int> que; 

    void pop(int value) {
        if (!que.empty() && value == que.front()) {
            que.pop_front();
        }
    }

    // 和上面队列的区别是这里换成了小于,
    void push(int value) {
        while (!que.empty() && value < que.back()) {
            que.pop_back();
        }
        que.push_back(value);

    }

    int front() {
        return que.front();
    }
};

int main() {
    string input;
    
    getline(cin, input);

    vector<int> nums;
    int k;

    // 找到并截取nums的部分
    int numsStart = input.find('[');
    int numsEnd = input.find(']');
    string numsStr = input.substr(numsStart + 1, numsEnd - numsStart - 1);
    // cout << numsStr << endl;

    // 用字符串流处理nums字符串提取数字
    stringstream ss(numsStr);
    string temp;
    while (getline(ss, temp, ',')) {
        nums.push_back(stoi(temp));
    }

    // 找到并提取k的值
    int kStart = input.find("k = ") + 4;
    k = stoi(input.substr(kStart));

    MyBigQueue queB; // 获取区间最大值
    MySmallQueue queS; // 获取区间最小值
    // vector<int> result;
    for (int i = 0; i < k; i++) { // 先将前k的元素放进队列
        queB.push(nums[i]);
        queS.push(nums[i]);
    }
    
    int result = queB.front() - queS.front();
    for (int i = k; i < nums.size(); i++) {
        queB.pop(nums[i - k]); // 滑动窗口移除最前面元素
        queB.push(nums[i]); // 滑动窗口前加入最后面的元素
        
        queS.pop(nums[i - k]);
        queS.push(nums[i]);
        
        result = max (result, queB.front() - queS.front());
    }
    cout << result << endl;
}