代码随想录算法训练营第 11 天 | LeetCode150. 逆波兰表达式求值 LeetCode239. 滑动窗口最大值 LeetCode347.前 K 个高频元素

代码随想录算法训练营

Day11 代码随想录算法训练营第 11 天 | LeetCode150. 逆波兰表达式求值 LeetCode239. 滑动窗口最大值 LeetCode347.前 K 个高频元素



前言

LeetCode150. 逆波兰表达式求值

讲解文档
视频讲解

LeetCode239. 滑动窗口最大值

讲解文档
视频讲解

LeetCode347.前 K 个高频元素

讲解文档
视频讲解


一、LeetCode150. 逆波兰表达式求值

1.题目链接

LeetCode

2.思路

(1)遍历字符串数组
(2)如果遇到数字,则放入栈中
(3)遇到符号,则弹出栈顶前两个元素,运算后压回栈中
(4)返回栈顶元素
细节:数组元素为字符串
1)判定是,以±*/作为判断条件更容易
2)将数字压入栈中时,用stoll()函数将字符串转换成long long类型
3)数据范围使得我们需要long long

3.题解

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> st;
        int n = tokens.size();

        for (int i = 0; i < n; i++) {

            if (tokens[i] == "+") {
                long long temp = st.top();
                st.pop();
                long long num = st.top();
                st.pop();
                st.push(num + temp);
            } else if (tokens[i] == "-") {
                long long temp = st.top();
                st.pop();
                long long num = st.top();
                st.pop();
                st.push(num - temp);
            } else if (tokens[i] == "*") {
                long long temp = st.top();
                st.pop();
                long long num = st.top();
                st.pop();
                st.push(num * temp);

            } else if (tokens[i] == "/") {
                long long temp = st.top();
                st.pop();
                long long num = st.top();
                st.pop();
                st.push(num / temp);
            } else {

                st.push(stoll(tokens[i]));
            }
        }
        return st.top();
    }
};

二、LeetCode239. 滑动窗口最大值

1.题目链接

LeetCode239. 滑动窗口最大值

2.思路

(1)难点:获取最大值
(2)不能用优先级队列,因为优先级队列会改变左右端点在队列中的位置
(3)实现单调队列表示滑动窗口
1)主体思路
三个方法pop、push、get_max
先建立第一个滑动窗口,将元素push进入队列
此后pop左端元素,push右端元素,get_max获取答案
2)方法实现
push:每个元素x在加入队列时,弹出它前面所有小于它的元素,最后将x加入队尾,使得每个元素前面都没有比自己小的元素,队首元素为滑动窗口最大值
pop:若要弹出x,则只有x为队首元素时需要弹出。弹出的是最左端元素,是最先入队的,如果x不是队首元素,那么它在最大值入队的时候一定被弹出
get_max:返回队首

3.题解

class myqueque {
public:
    deque<int> q;
    void pop(int x) {
        if (!q.empty() && x == q.front())
            q.pop_front();
    }
    void push(int x) {
        while (!q.empty() && x > q.back())
            q.pop_back();
        q.push_back(x);
    }
    int get_max() { return q.front(); }
};
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        myqueque q;
        int n = nums.size();
        vector<int> ans;
        for (int i = 0; i < k; i++) {
            q.push(nums[i]);
        }
        ans.push_back(q.get_max());
        for (int i = k; i <= n - 1; i++) {
            q.pop(nums[i - k]);
            q.push(nums[i]);
            ans.push_back(q.get_max());
        }
        return ans;
    }
};

五、LeetCode347.前 K 个高频元素

1.题目链接

LeetCode347.前 K 个高频元素

2.思路

大顶堆和小顶堆适合解决前k个高频元素/低频元素
(1)为什么选择小顶堆:
在堆的元素多于k个时,需要弹出元素,而优先从根节点弹出元素,若用大顶堆则会丢失最大值
(2)小顶堆和大顶堆的数据结构:优先队列priority_queue
(3)过程:
三个任务:求频率、排序、取前K个
1)先遍历数组,将元素和频率放进map,元素为key,频率为value,便于同时保存元素和频率
2)遍历映射,将映射压入优先队列,再判断优先队列大小,如果优先队列大小超过k,则pop
3)最后将优先队列中每个映射的value赋给数组
(4)本题一些易错的语法
1)priority_queue定义
2)重载运算符
3)map迭代器的使用

3.题解

class Solution {
public:
    class compare
    {
        public :
        bool operator()(pair<int,int>& p1,pair<int,int>& p2)
        {
            return p1.second>p2.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        int n=nums.size();
        unordered_map <int,int>m;
        for(int i=0;i<n;i++)
        {
            m[nums[i]]++;
        }
        priority_queue<pair<int,int>,vector<pair<int,int>>,compare> q;
        for(unordered_map<int,int>::iterator it=m.begin();it!=m.end();it++)
        {
            q.push(*it);
            if(q.size()>k)q.pop();
            
        }
        vector<int> res;
        for(int i=k-1;i>=0;i--)
        {
            res.push_back(q.top().first);
            q.pop();
        }
        return res;
    }
};

总结

本章重点
1、用队列实现栈
2、用站实现队列
3、栈的应用:逆波兰式、有效括号
4、队列应用:滑动窗口最大值
5、优先队列:本质是大顶堆和小顶堆,前k个高频元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值