DAY11 - 150. 逆波兰表达式求值, 239. 滑动窗口最大值, 347.前 K 个高频元素

150. 逆波兰表达式求值

同样使用栈,碰到数字就入栈,碰到运算符就出栈两个数字进行运算结果,将结果入栈

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(string s:tokens){
            if(s=="+"||s=="-"||s=="*"||s=="/"){
                int a=st.top();
                st.pop();
                int b=st.top();
                st.pop();
                if(s=="+") st.push(a+b);
                if(s=="-") st.push(b-a);
                if(s=="*") st.push(a*b);
                if(s=="/") st.push(b/a);
            }else{
                st.push(stoi(s));
            }
        }
        return st.top();
    }
};
  • stoi() string to int, stoll string to long

239. 滑动窗口最大值

暴力解法时间复杂度是 n*k,用队列尝试用 O(N) 解决。

单调队列:队列中保证单调递增(递减)

queue和deque

最大区别:deque两端可进出,并且元素可随机访问

image-20250325144136623

容器适配器(queue stack)是不支持迭代器的

class Solution {
private:
    class MyQue{
    public:
        deque<int> que;
        void push(int x){
            while(!que.empty()&&x>que.back()){
                que.pop_back();
            }
            que.push_back(x);
        }

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

        int front(){
            return que.front();
        }
    };

public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQue que;
        vector<int> res;
        // 初始化窗口
        for(int i=0;i<k;i++){
            que.push(nums[i]);
        }
        res.push_back(que.front());

        for(int i=k;i<nums.size();i++){
            que.pop(nums[i-k]);
            que.push(nums[i]);
            res.push_back(que.front());
        }
        return res;
    }
};

还是有点难度的。而且感觉自定义pop那里是不是有点问题?只比较值的话碰到重复的值是不是就会错误操作?=》想了一下好像不会,因为有重复值说明进来了一个,又出去一个也没问题。

347.前 K 个高频元素

class 和 struct

相同点

  1. 功能相同

    • classstruct 都可以用来定义一个复合类型(用户自定义类型),其中可以包含成员变量、成员函数、构造函数、析构函数、运算符重载等。

    • 它们都可以继承其他类、实现多态、支持模板等。

  2. 语法相似

    • 它们的语法几乎是一样的。比如定义一个成员函数、变量等,在 classstruct 中都是相同的。

不同点

  1. 默认的成员访问权限

    • struct:默认的成员访问权限是 public

    • class:默认的成员访问权限是 private

  2. 使用场景

    • struct 通常用于简单的数据结构,尤其是在需要公有数据成员并且成员之间没有复杂的封装、继承等特性时。C 语言使用的结构体是 struct 类型。
    • class 通常用于复杂的对象,特别是在面向对象编程中,class 用于实现数据封装、继承、多态等特性。

priority_queue

priority_queue<T, Container, Compare> pq;
  • T:队列中存储的元素类型。
  • Container:底层容器类型,默认是 vector。你也可以指定其他容器类型,比如 deque
  • Compare:一个比较函数或函数对象,指定队列中的元素如何排序。默认是大顶堆,要改成小顶堆要重载运算符。
struct mycompare{
        bool operator()(const pair<int,int> &a, const pair<int,int> &b){
            return a.second > b.second; //注意是大于
        }
    };

关于unordered_map的查找插入写法

以下两段代码等价

	unordered_map<int,int> map;
    for(int n:nums){
        auto it=map.find(n)
        if(it!=map.end()){
            it->second++;
        }else{
            map.insert({n,0});
        }
    }

简单写法

	unordered_map<int, int> map;
    for (int n:nums) {
        map[n]++;   //map会自动处理插入新键值对
    }

答案

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

    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> map;
        for(int n:nums){
            map[n]++;
        }

        priority_queue<pair<int,int>, vector<pair<int,int>>, mycompare> pq;
        for(auto m:map){
            pq.push(m);
            if(pq.size()>k){
                pq.pop();
            }
        }

        vector<int> res;
        while(!pq.empty()){
            res.push_back(pq.top().first);
            pq.pop();
        }
        return res;
    }
};
  • 注意,vector<int> res(k) 这行代码会初始化一个大小为 kvector<int>,其中的每个元素都被默认初始化为 0。所以再 res(k) 后面再 push_back 就会导致数组大小大于k,正确的写法是通过索引直接填充而不是用 push_back
posted @ 2025-03-25 19:57  ChloeChen0221  阅读(5)  评论(0)    收藏  举报