算法刷题Day 13 滑动窗口最大值+前K个高频元素

Day 13 栈和队列

239. 滑动窗口最大值

乍一看有点单调栈的意思,但其实不是。

仔细想想应该是用优先队列,似乎也不对,从滑动窗口出来的元素不好从队列中删除

看了随想录之后,是用到单调队列

使用单调队列有坑的地方:

case:nums =[-7,-8,7,5,7,1,6,0], k = 4

单调队列在push的时候,如果红框为>=号,那么结果会出错

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9t625hHF-1687149547971)(E:\OneDrive\面试资料\训练营\LC239-滑动窗口最大值.assets\image-20230617144701762.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4DtHe5Ve-1687149547973)(E:\OneDrive\面试资料\训练营\LC239-滑动窗口最大值.assets\image-20230617144724157.png)]

正确的写法:相等的话,也要插入单调队列中

class Solution {
    class MaxQueue
    {
        int len;
        deque<int> que;
    
    public:
        int front()
        {
            return que.front();
        }

        void pop(int val)
        {
            if (val == que.front())
            {
                que.pop_front();
            }
        }

        void push(int val)
        {
            while (!que.empty() && val > que.back())
            {
                que.pop_back();
            }
            que.push_back(val);
        }
    };

public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MaxQueue slideWin;
        vector<int> rst;

        auto iter = nums.begin();
        while (k-- && iter != nums.end())
        {
            slideWin.push(*iter++);
        }
        rst.push_back(slideWin.front());
        auto discard = nums.begin();

        while (iter != nums.end())
        {
            slideWin.pop(*discard);
            slideWin.push(*iter);
            rst.push_back(slideWin.front());
            discard++;
            iter++;
        }

        return rst;
    }
};

347. 前K个高频元素

首先想到的是优先队列

设计仿函数的时候,记得要把operator()函数的权限设置为public

因为类默认是私有的访问权限,而operator()是要被调用的

class Solution {
    class CmpPair {
    public:
        bool operator()(const pair<int, int> &a, const pair<int, int> &b) {
            return a.second < b.second;
        }
    };

public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> table;

        for (auto num : nums)
        {
            table[num]++;
        }

        priority_queue<pair<int, int>, vector<pair<int, int>>, CmpPair> que;
        for (auto &item : table)
        {
            que.push(item);
        }

        vector<int> rst;
        for (int i = 0; i < k; ++i)
        {
            rst.push_back(que.top().first);
            que.pop();
        }

        return rst;
    }
};

以上是我的实现,其实跟排一次序没有区别。代码随想录里的实现还限制了优先队列里的元素个数为k

可以改进一下

这个时候排列的顺序要从小到大

class Solution {
    class CmpPair {
    public:
        bool operator()(const pair<int, int> &a, const pair<int, int> &b) {
            return a.second > b.second;
        }
    };

public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> table;

        for (auto num : nums)
        {
            table[num]++;
        }

        priority_queue<pair<int, int>, vector<pair<int, int>>, CmpPair> que;
        for (auto &item : table)
        {
            que.push(item);
            if (que.size() > k)
            {
                que.pop();
            }
        }

        vector<int> rst(k);
        for (int i = k - 1; i >= 0; --i)
        {
            rst[i] = que.top().first;
            que.pop();
        }

        return rst;
    }
};

你可能感兴趣的:(算法)