代码随想录算法训练营第十天 |栈与队列进阶

逆波兰表达式求值

逆波兰表达式其实就是后缀表达式
stoll函数将字符串转换为long long int,stl函数将字符串转换为long int
注意,是后弹出来的去除以前面弹出来的

报错,c++单双引号的使用
在这里插入图片描述
在这里插入图片描述
题目里也是用的双引号
在这里插入图片描述

滑动窗口最大值

第一时间想到是暴力 外面n次里面k次,很明显10的5次方乘10的4次方,超时了

注意题目:要求返回的是滑动窗口中的最大值!不是队列的和的最大值,别想当然了,

所以使用单调移动队列的方法

在这里插入图片描述
先入栈一个元素,再准备入栈一个元素,如果上一个元素小于下一个元素,那上一个元素就没必要保持维护了,直接出栈即可

我们选择用deque这个数据结构来实现单调队列,常用的queue在没有指定容器的情况下,deque就是默认底层容器。

这里有一些不理解,private里定义public?
在这里插入图片描述

class Solution {
    class MyQue{
    public:
        deque<int>que;
        void pop(int value){
            if(!que.empty()&&que.front()==value) que.pop_front();
        }
        void push(int value){
            while(!que.empty()&&value>que.back()) que.pop_back();//注意这里全是back,并且大于即可,因为pop里会处理等于的情况,如果这里把等于的踢出去了,那么pop(nums[i-k])的时候就会把仅存的那个给pop掉 使得队列为空了),所以这里必须是大于,做题逻辑要统一,大于等于就是单调队列里面都是大于等于
            que.push_back(value);
        }
        int front(){
            return que.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQue que;
        vector<int> result;
        for(int i=0;i<k;i++) que.push(nums[i]);
        result.push_back(que.front());
        for(int i=k;i<nums.size();++i){
            que.pop(nums[i-k]);
            que.push(nums[i]);
            result.push_back(que.front());
        }
        return result;
    }
};

题目三:前k个高频元素

大小堆顶的经典题目,也就是c++的优先级队列

统计出现频率,用map实现

小顶堆还是大顶堆?在这里插入图片描述

本题如果调用C++库map和priority_queue就不难 但要熟悉库函数用法

同时,这里要使用自己的定义函数以比较map数组,

以下解释了为什么小顶堆是return left>right,与快排中相反。

在这里插入图片描述

class Solution {
public:
    // 小顶堆
    class mycomparison {
    public:
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
            return lhs.second > rhs.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        // 要统计元素出现频率
        unordered_map<int, int> map; // map<nums[i],对应出现的次数>
        for (int i = 0; i < nums.size(); i++) {
            map[nums[i]]++;
        }

        // 对频率排序
        // 定义一个小顶堆,大小为k
        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;

        // 用固定大小为k的小顶堆,扫面所有频率的数值
        for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
            pri_que.push(*it);
            if (pri_que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                pri_que.pop();
            }
        }

        // 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        vector<int> result(k);
        for (int i = k - 1; i >= 0; i--) {
            result[i] = pri_que.top().first;
            pri_que.pop();
        }
        return result;

    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值