day13 代码回想录 栈和队列3 滑动窗口最大值&前 K 个高频元素

大纲

● 239. 滑动窗口最大值
● 347.前 K 个高频元素

滑动窗口最大值

题目链接:239. 滑动窗口最大值
分析过程:
注意题目要求是返回从0到n-k的窗口移动过程中的最大值数组,这和求整个窗口移动过程中的最大值是有区别的。
本题是有难度的,因为要求在O(n)时间范围内解决问题。
这就需要利用到单调队列了,需要实现一个队列,可以移除队头元素和加入队尾元素,同时告诉当前队列中的最大值是多少。

class MyQueue { //单调队列(从大到小)
public:
    deque 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();
    }
};

前 K 个高频元素

题目链接:347.前 K 个高频元素
分析过程:
题目要求返回数组中前k个值,这里的难点是在不排序的情况下,使用优先队列来解决问题。
需要使用的是最小堆,因为最大堆需要操作两遍来得到前k个最大值,而最小堆只需要一次,使用排除法来删除不是前k个元素。

// 使用最小堆去除不是前k的值
// 返回结果

// 比较函数 最小堆,默认是最大堆
class priority_less {
public:
    bool operator()(const pair& val1, const pair& val2) {
        return val1.second > val2.second;
    }
};

vector getKthVals(vector& nums, int k)
{
    map timesMap;
    for (int i = 0; i < nums.size(); ++i) {
        if (timesMap.find(nums[i]) != timesMap.end()) {
            timesMap[nums[i]] += 1;
        } else {
            timesMap[nums[i]] = 1;
        }
    }
    // 最小堆
    priority_queue, vector>, priority_less> proo;
    for (auto pair : timesMap) {
        proo.push(pair);
        if (proo.size() > k) {
            proo.pop(); // 弹出顶部最小
        }
    }

    vector ret;
    while (!proo.empty()) {
        auto pair = proo.top();
        ret.push_back(pair.first);
        proo.pop();
    }

    return ret;
}

总结

本篇的两道题目比较有难度,就算知道思路实现起来也不容易。
使用到了单调队列及优先队列,需要实现比较函数。

你可能感兴趣的:(c++,算法,栈队列)