代码随想录算法训练营第十一天| leetcode 150、239、347

逆波兰表达式求值 leetcode 150

1.逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面。

平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。其优点是去掉括号无歧义便于计算机计算,适合栈操作运算,遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中。

后缀表达式就相当于后序遍历(左右根)如图二叉树,中缀表达式就相当于中序遍历。

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<long long> sta;
        for(int i=0;i<tokens.size();i++){
            if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
                long long num1=sta.top(); sta.pop();
                long long num2=sta.top(); sta.pop();
                if(tokens[i]=="+") sta.push(num2+num1);
                else if(tokens[i]=="-") sta.push(num2-num1);
                else if(tokens[i]=="*") sta.push(num2*num1);
                else sta.push(num2/num1);
            }
            else sta.push(stoll(tokens[i]));
        }
        int res=sta.top();
        sta.pop();
        return res;
    }
};

总结

1.long long:是 C++ 中的一种整数类型,通常至少有 64 位(8 字节)。这意味着它可以表示的整数范围至少是从 -2^63 到 2^63 - 1。

2.stoll:是 C++ 标准库中的一个函数,属于<sstream>头文件,用于将一个字符串转换为一个long long类型的整数。

出现的错误

1.从栈顶取出两个数字进行运算时,后取出的num2应该放在运算符前面,否则作减法除法时会出错。

2.库函数pop()返回值是一个void类型,所以不能直接返回sta.pop(),应该先获取sta.top(),再pop()。之前用队列实现栈时,我们实现的pop函数是可以返回栈顶元素的然后再弹出。

滑动窗口最大值 leetcode 239

使用双端队列deque构造一个单调队列(从大到小),单调队列要push的元素val如果大于队尾元素,那么就将队尾元素弹出直到队列中队尾元素大于val或者队列为空,之后再将val push到队尾,单调队列要pop的元素如果等于队首元素那么就pop,如果要pop的元素小于队首元素那就什么都不做(因为push函数就已经把“小”的元素pop了),这样无论怎么pop和push队列中的元素都是按照单调递增的规律排列而且队首元素一定是最大的。

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

先把前k个元素放入我们自己定义的que中,然后使用for循环遍历数组,i指向要push的新元素,i-k的索引就是要pop的元素,每次遍历都记录最大值。

前k个高频元素 leetcode 347

做这道题之前先学一点点小知识

1.大根堆(Max Heap)和小根堆(Min Heap):两种特殊的数据结构,它们都是完全二叉树,但在比较节点时遵循不同的规则。 大根堆中,父节点的值大于或等于其子节点的值;而小根堆中,父节点的值小于或等于其子节点的值。 这种特性使得大根堆可以用于实现优先队列中的最大元素查找,而小根堆则适用于最小元素查找。

2.优先级队列(priority_queue):使用STL库中的priority_queue容器适配器来实现,默认情况下priority_queue是一个大根堆(默认使用less<T>比较),如果需要最小堆,可以通过传递greater<T>()作为比较函数。

//大根堆优先级队列
priority_queue<int> maxHeap;
//小根堆优先级队列
priority_queue<int,vector<int>,greater<int>> minHeap; 

我们也可以自定义来实现我们想要的优先级队列

//priority_queue<元素类型,存储容器,自定义比较函数>
priority_queue<pair<int,int>,vector<pair<int,int>>,myComparison> que;

上述代码实现的优先级队列中的每一个元素都是包含两个整数的对pair,使用vector作为存储元素的底层容器。这意味着队列中的元素会被存储在一个动态大小的数组中,数组的元素类型是pair<int,int>,myComparison自定义的比较函数用于定义队列中元素的比较规则。

3.优先级队列的比较函数

priority_queue的期望比较器是通过operator(),也就是()重载运算符实现的,到这就又有疑问了比较大小为什么不是“<”或“>”重载运算符呢?首先operator()可以接受任意数量和类型的参数,其次如果后续需要修改比较逻辑,operator()可以更容易地适应新的需求,而不需要受到<或>操作符的固定形式限制。

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;
        for(int i=0;i<nums.size();i++){
            map[nums[i]]++;
        }
        priority_queue<pair<int,int>,vector<pair<int,int>>,MyComparison> pri_que;
        auto it=map.begin();
        for(;it!=map.end();it++){
            pri_que.push(*it);
            if(pri_que.size()>k) pri_que.pop();
        }
        vector<int> res(k);
        for(int i=k-1;i>=0;i--){
            res[i]=pri_que.top().first;
            pri_que.pop();
        }
        return res;
    }
};

总结

1.当使用greater作为比较函数时,优先级队列会认为较大的元素具有较低的优先级。因此,最小的元素会位于堆的顶部,从而形成小根堆。

2.因为小顶堆先弹出的是最小的,所以倒序输入到数组。

出现的错误

1.MyComparison中没有写public,导致重载函数默认为私有成员,编译出错。

  • 15
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值