LeetCode Day15栈与队列2

239 滑动窗口最大值

题目理解

给定整数数组nums,以k个数字为单位,寻找k个数字中的最大值。
在这里插入图片描述

思路

①超时的暴力解法:一开始想到的就是两层循环,一层遍历数组元素,直到第size()-k位,另一层寻找k个数字中的最大值。时间复杂度为O(kn)。
②题解中的方法,利用单调队列来处理数组。
首先,题目是寻找滑动窗口中的最大值,每次移动,相应的窗口会少一个元素再加一个元素,和出队、入队的操作很相似。我们需要的队列操作应该是每次pop一个元素,push一个元素,然后队首元素为队列中的最大值,也就是我们需要的结果,这样的话只有队列是严格单调递减的时候才能保证队首元素是最大值。
队列是一种容器适配器,需要底层容器来实现,缺省情况下用deque来实现。deque是一种双端队列,可在队首队尾进行push和pop操作。
对于push操作,想要将要push的元素和当前队列的队尾元素进行比较,因为我们要保证队列严格单调递减,所以如果当前元素值大于队尾元素,则队尾元素必定对滑动窗口最大值没有影响,舍去,这样直到当前元素小于队首元素,再加入队列。
对于pop操作,因为上一步的push操作会可能会舍去一部分元素,所以数组当前值可能已经不在队列中,因此需要判断队首元素是否是数组当前值,是的话pop,不是的话则不进行操作。

代码

class Solution {
private:
    class Queue {
    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 front() {
            return que.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        Queue 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;
    }
};

347 前K个高频元素

题目理解

给定数组,返回数组中出现频率最高的前K个元素。
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

思路

可以用哈希表把数组中不同元素出现的次数记录下来,接下来需要做的是怎样找到出现次数为前K大的元素呢。
考虑用优先级队列,也就是最小堆,队列长度为K,因为最小堆中每次弹出最小的元素,这样最后处理完哈希表后,剩下的K个元素即为最大的K个元素。

代码

class Solution {
public:
    class com {
    public:
        bool operator()(pair<int,int>& p1,pair<int,int>& p2) {
            return p1.second > p2.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int,int> ma;
        vector<int> res;
        for(auto c : nums) 
            ma[c]++;
        priority_queue<pair<int,int>,vector<pair<int,int>>,com> pri;
        for(unordered_map<int,int>::iterator it = ma.begin();it != ma.end();it++) {
                pri.push(*it);
                if(pri.size()>k)
                	pri.pop();
            }
        }
        while(!pri.empty()) {
            res.push_back(pri.top().first);
            pri.pop();
        }
        reverse(res.begin(),res.end());
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]提供了一个朴素的解法,使用两个来存储字符串,一个用来存储普通字符,另一个用来存储特殊字符。遍历字符串,如果是普通字符则压入第一个,如果是特殊字符则弹出第一个顶元素。最后比较两个是否相同即可判断字符串是否有效。这个解法的时间复杂度是O(M + N),空间复杂度也是O(M + N)。\[1\] 引用\[2\]提供了另一个的应用场景,即判断括号是否有效。遍历字符串,如果是左括号则压入,如果是右括号则判断和顶元素是否匹配,不匹配则返回false,匹配则弹出顶元素。最后判断是否为空即可判断括号是否有效。\[2\] 引用\[3\]也提供了一个判断括号是否有效的解法,使用来操作。遍历字符串,如果是左括号则压入,如果是右括号则判断和顶元素是否匹配,不匹配则返回false,匹配则弹出顶元素。最后判断是否为空即可判断括号是否有效。这个解法使用了HashMap来存储括号的对应关系。\[3\] 综上所述,在解决字符串相关问题中有着广泛的应用,包括判断字符串是否有效、逆波兰表达式等。在解决这些问题时,可以帮助我们保存和处理字符的顺序,从而简化问题的处理过程。 #### 引用[.reference_title] - *1* *3* [Leetcode刷题03-](https://blog.csdn.net/weixin_47802917/article/details/123007699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] - *2* [leetCode-类型详解](https://blog.csdn.net/zhiyikeji/article/details/125508011)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值