代码随想录算法训练营三期 day13 - 栈与队列(3)

239. 滑动窗口最大值(单调队列)

原文链接:239. 滑动窗口最大值
题目链接:239. 滑动窗口最大值
视频链接:单调队列正式登场!| LeetCode:239. 滑动窗口最大值
难点:如何求一个区间里的最大值(暴力的复杂度是 O ( n k ) O(nk) O(nk)) ?
其实队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。那么这个维护元素单调递减的队列就叫做单调队列。
设计单调队列的时候, p o p pop pop p u s h push push 操作要保持如下规则:
p o p ( v a l u e ) pop(value) pop(value):如果窗口移除的元素 v a l u e value value 等于单调队列的出口 ( f r o n t front front) 元素,那么队列弹出元素,否则不用任何操作;
p u s h ( v a l u e ) push(value) push(value):如果 p u s h push push 的元素 v a l u e value value 大于入口 ( b a c k back back) 元素的数值,那么就将队列入口的元素弹出,直到 p u s h push push 元素的数值小于等于队列入口元素的数值为止。
代码随想录算法训练营三期 day13 - 栈与队列(3)_第1张图片
代码如下:

class Solution {
private:
    class MyQue {
        public:
            deque<int> dq;
            void pop(int val) {
                if (!dq.empty() && val == dq.front()) {
                    dq.pop_front();
                }
            }
            void push(int val) {
                while (!dq.empty() && val > dq.back()) {
                    dq.pop_back();
                }
                dq.push_back(val);
            }
            int getMaxValue() {
                return dq.front();
            }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> res;
        MyQue que;
        for (int i = 0; i < k; i++) {
            que.push(nums[i]);
        }
        res.push_back(que.getMaxValue());
        for (int i = k; i < nums.size(); i++) {
            que.pop(nums[i - k]);
            que.push(nums[i]);
            res.push_back(que.getMaxValue());
        }
        return res;
    }
};

347. 前 K 个高频元素(优先队列)

原文链接:347. 前 K 个高频元素
题目链接:347. 前 K 个高频元素
视频链接:优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode:347.前 K 个高频元素
这道题目主要涉及到如下三块内容:
(1) 要统计元素出现频率 (使用 m a p map map 进行统计)
(2) 对频率排序 (优先队列/堆)(3) 找出前K个高频元素
我们要用小顶堆,因为要统计前 k k k 个最大元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前 k k k 个最大元素。
代码随想录算法训练营三期 day13 - 栈与队列(3)_第2张图片
注意左大于右是建立小顶堆(与快排相反)!

class Solution {
private:
    class myCmp {
    public:
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
            return lhs.second > rhs.second;
        }
    };
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> map;
        // 统计元素出现频率
        for (int i = 0; i < nums.size(); i++) {
            map[nums[i]]++;
        }
        // 构建小顶堆
        priority_queue<pair<int, int>, vector<pair<int, int>>, myCmp> prique;
        for (auto it : map) {
            prique.push(it);
            if (prique.size() > k) {
                prique.pop();
            }
        }
        // 倒序构建数组
        vector<int> res(k);
        for (int i = k - 1; i >= 0; i--) {
            res[i] = prique.top().first;
            prique.pop();
        }
        return res;
    }
};

你可能感兴趣的:(Algorithms,算法,leetcode,数据结构)