文章链接: 150. 逆波兰表达式求值 239. 滑动窗口最大值  347.前 K 个高频元素

视频链接: 150. 逆波兰表达式求值 239. 滑动窗口最大值  347.前 K 个高频元素

题目链接: 150. 逆波兰表达式求值 239. 滑动窗口最大值  347.前 K 个高频元素

思路:

150.逆波兰表达式求值

  1. 遇到数字就将数字放进栈里;
  2. 遇到符号就将栈顶的两位作相应的运算,做完运算后再放回栈里;
  3. 以此类推,直到栈中只剩最后一个元素,即为答案。
class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> st;
        for(int i = 0; i < tokens.size(); i++) {
            if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){
                int num1 = st.top();
                st.pop();
                int num2 = st.top();
                st.pop();
                if(tokens[i] == "+") st.push(num2 + num1);
                if(tokens[i] == "-") st.push(num2 - num1);
                if(tokens[i] == "*") st.push(num2 * num1);
                if(tokens[i] == "/") st.push(num2 / num1);
            }else {
                st.push(stol(tokens[i]));
            }
        }

        int result = st.top();
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

239.滑动窗口最大值

如何写一个“单调队列”(单调递减的队列)?

  1. 定义一个双向队列;
  2. 定义 pop() 函数:删除最前面的值;
  3. 定义 push() 函数:将队列里小于 value(要放进去队列的数) 值的删除,再将 value 放进去;(关键
  4. 定义 front() 函数:返回队列的最前面的值(单调队列的出口处的值);
class Solution {
private:
    class MyQueue { // 单调队列
    public:
        deque<int> que; // 双向队列
        void pop(int value) { 
            if (!que.empty() && value == que.front()){
                que.pop_front();
            }
        }

        void push(int value){
            while(!que.empty() && value > que.back()){ // 将小于value的数值都pop掉
                que.pop_back();
            }
            que.push_back(value);
            // 保持了队列里的数值是单调从小到大
        }

        int front(){
            return que.front();
        }
    };
    
    public : vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQueue 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;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.


347.前 K 个高频元素

最适合解法大顶堆小顶堆  --> 优先级队列(priority_queue

该题:小顶堆

class Solution {
public:
    class mycompzrion{ // 重载运算符
    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>>, mycompzrion> pri_que;
        // 定义一个小顶堆
				
        for(unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++){
        // 更新前k个高频的数
            pri_que.push(*it);
            if(pri_que.size() > k){
                pri_que.pop();
            }
        }

        vector<int> result(k);
        for(int i = k - 1; i >= 0; i--){ // 因为是小根堆,所以要反向输出
            result[i] = pri_que.top().first;
            pri_que.pop();
        }
        
        return result;
    }
};
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.


困难:

150.逆波兰表达式求值

stoll() 是什么函数?

此函数将在函数调用中作为参数提供的字符串转换为long long int。

补充stol():此函数将在函数调用中作为参数提供的字符串转换为long int。


239.滑动窗口最大值

:什么是“C++ 继承访问权限控制(public,protected,private)”?

 C++ 继承访问权限控制(public,protected,private) - 菜鸟教程 (cainiaojc.com)

:解释deque(双向队列) ?

deque是一个双向队列(double-ended queue),可以在队列的两端进行元素的插入和删除操作。其是C++STL(标准模板库)中的一种容器,可以用于存储各种类型的元素。deque的特点是可以在队列的两端进行元素的操作,并且可以高效地在队列的任意位置进行元素的插入和删除操作。


347.前 K 个高频元素

:为什么用小顶堆不用大顶堆?

:因为pop的时候,可以直接pop掉最小的;用大顶堆的话,pop的时候会pop掉最大的(本题中就是最高频的。)


:重载运算符operator

:(参考: C++ operator()(重载小括号符) - 简书 (jianshu.com)

C++的类可以重载()【即小括号符】,来实现仿函数,或者叫函数对象

基本使用方式

class FuncClass
{
public:
    void operator()(const string& str) const
    {
        std::cout << str << std::endl;
    }
}; 
int main() 
{ 
    FuncClass myFuncClass; 
    myFuncClass("hello world"); 
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.


map ::iterator it 的用法。

:(参考: map<int,int>::iterator it 的用法_map<int, int>::iterator it;-CSDN博客

 map iterator pair priority_queue C++_c++ map迭代器-CSDN博客

这种方法能够取出保存在map容器里面的数据。

:优先队列的相关知识?

priority_queue<Type, Container, Functional>, 其中Type为数据类型,Container为保存数据的容器,Functional为元素比较方式。如上:

priority_queue<pair<int, int>, vector<pair<int, int>>, mycompzrion> pri_que;
// 定义一个小顶堆
  • 1.
  • 2.

注意:Container必须是用数组实现的容器。

(参考: https://blog.csdn.net/qq_41687938/article/details/117827166


今日收获:

这是前天的任务,拖着拖着写了三天。主要学习了对栈(第一题)和队列(后两题)的应用,学会了如何定义一个“单调队列”,如何定义一个“小根堆”。