代码随想录11天打卡

34、逆波兰数

力扣原题

题目简介:

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*''/'
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

初见思路:

没有这东西

算法思路:

​ 利用栈可以正确的处理后序排列的表达式,我学到了。第二、我还学到了stoll,可以很方便的把string变成int

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

        stack<int> stack1;
        for (int i = 0; i < n; i++) {
            if (tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" ||
                tokens[i] == "/") {
                int temp1 = stack1.top();
                stack1.pop();
                int temp2 = stack1.top();
                stack1.pop();
                if (tokens[i] == "+") {
                    stack1.push(temp1 + temp2);
                } else if (tokens[i] == "-") {
                    stack1.push(temp2 - temp1);
                } else if (tokens[i] == "*") {
                    stack1.push(temp1 * temp2);
                } else if (tokens[i] == "/") {
                    stack1.push(temp2 / temp1);
                }
            } else {
                stack1.push(stoll(tokens[i]));
            }
        }
        return stack1.top();
    }
};

35、滑动窗口最大值

力扣原题

题目简介:

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值

初见思路:

​ 我想的就是两层循环把,外层遍历有多少个窗口,内层就遍历滑动窗空中的最大值。然后就水灵灵的超时了。用队列来优化嘛?怎么优化,我知道滑动窗口就是一个队列,一个进来就出去一个。这样可以节省时间吗?哪部分的时间呢?

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> res;
        for (int i = 0; i <= n - k; i++) {
        
            int max = INT32_MIN;
            for (int j = 0; j < k; j++) {
                if (nums[i + j] > max) {
                    max = nums[i + j];
                }
            }
            res.push_back(max);
        }
        return res;
    }
};

算法思路:

​ 我觉得算法思路里节省的还是内循环的比较过程,因为他一直维护了仍存活的最大值,而我们上面的最大值其实只存活了一次循环,结束之后我们又要再维护一个最大值,当k足够大的时候,很自然就会拉长时间了。而算法的思路就是一直保持存活的最大值。

class Solution {
public:
    deque<int> que;


    void pop(int val){
        if(!que.empty() && que.front() == val){
            que.pop_front();
        }
    }

    void push(int val){
        while(!que.empty() && val > que.back()){
            que.pop_back();
        }
        que.push_back(val);
    }

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

    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> res;
        for(int i=0;i<k;i++){
            push(nums[i]);
        }
        res.push_back(get_max());
        for(int i =0 ; i<n-k; i++ ){
            pop(nums[i]);
            push(nums[i+k]);
            res.push_back(get_max());    
        }
        return res;
    }
};

36、K个高频元素

力扣原题

题目简介:

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

初见思路:

​ 遍历一遍数组,我就知道各个元素都出现了多少次了,最麻烦的是如何维护一个从大到小的根据出现次数的队列呢。优选队列可以自动维护一个单调队列我知道,但是我怎么根据出现的次数对应到哪个元素呢?定义一个map再存一下各个元素的出现次数吗?但是key是元素,次数是value呀,我怎么根据valuekey呢?

算法思路:

class Solution {
public:
    
    class mycomparisom{
public:
        bool operator()(const pair<int,int>& p1,const pair<int,int> &p2) const{
            return p1.second > p2.second;
        }

    };
    
    vector<int> topKFrequent(vector<int>& nums, int k) {
        int n = nums.size();
        unordered_map<int,int> map1;
        for(auto a : nums){
            map1[a]++;
        }

        priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparisom> minHeap;

        for(auto b = map1.begin();b !=map1.end();b++){
            minHeap.push(*b);
            if(minHeap.size() > k) minHeap.pop();
        }
        vector<int> res;
        for(int i =0;i<k;i++){
            int temp = minHeap.top().first; 
            res.push_back(temp);
            minHeap.pop();
        }   
        return res;

    }
};

​ 问题还是出在我对优先队列的不熟悉呀:

​ 1、确实是用map存入了次数和元素,这样才能找到对应关系。

​ 2、如何利用优先队列呢,首先优先队列是可以自己定义比较方式的,也就是上方使用的仿函数方法,通过这个我们就可以定义如何存放优先队列中的值

​ 3、定义优先队列的方式,你要给出元素的类型,给出存放的形式,也就是vector<pair<int,int>>,然后给出自己比较的规则

​ 4、大顶堆和小顶堆的实现方式,return的时候,如果判断为真,就把操作数2放到前面,操作数1放到后面。

​ 5、如果你想保留最大的k个值,你就要用小顶堆,这样再pop的时候,才会把堆顶的数给pop出去,反之亦然。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值