Day13|Leetcode 239. 滑动窗口最大值 Leetcode 347. 前 K 个高频元素

刚考完试,休息了一天,一天写两天的东西,好累

Leetcode 239 滑动窗口最大值

题目链接 239 滑动窗口最大值

本题目其实用暴力的方法还是比较好想的,但是由于有限定时间,所以就可以用数据结构——队列,因为我们要取到最大值,所以我们要用单调队列:

这个题目难想的点就是怎么维护最大值:我们要维护最大值就要将最大值放到队列的出口,这样我们方便取最大值,既然要放到队列出口,我们就要保证队列中的元素单调递减才行,所以这里运用到了单调队列,最关键的两点:第一,我们需要在对队列输入元素时,将即将要进入的元素和前面的元素做对比,如果比前面的元素大就需要将前面的元素一个一个弹出,反之就不弹出,就直接将该元素直接输入队列中,第二就是在滑动到下一个区间时,如果最大值(队列front的值)如果和即将脱离区间的元素一样的话,就要将队列中的front元素弹出,重新第一步的操作,还要强调一点,需要将最大值都用vector储存一下。

整体就是这个思路,下面就是上代码:

class Solution {
    private:
    class MyQueue{
    public:
    deque<int> que;
    //与即将脱离窗口区间的值相等就弹出//更新区间元素
    void pop(int val){
        if(!que.empty()&&val == que.front()){
            que.pop_front();
        }
    }
    //输入元素,并且我们原则是保留尽可能大的值,按照单调递减排序
    // 如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
    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) {
            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;
    }

};

Leetcode 347. 前 K 个高频元素

题目链接 347 前 K 个高频元素

本题目可以用的方法有很多,其实最简单的就是sort排序,可是时间复杂度不合适,我们学习一种新的方法,优先级队列,首先优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列。而且优先级队列内部元素是自动依照元素的权值排列。在缺省状态下(即系统默认状态)priority_queue利用max-heap(大顶堆)完成对元素的排序,这个大顶堆是以vector为表现形式的complete binary tree(完全二叉树)。堆是一棵完全二叉树,树中每个结点的值都不小于(或不大于)其左右孩子的值。 如果父亲结点是大于等于左右孩子就是大顶堆,小于等于左右孩子就是小顶堆。在这之前,我们需要统计元素出现的频率,这一类的问题可以使用map来进行统计。(前面讲过哈希中的map),然后对频率进行排序就用优先级队列,还有一个问题就是是用大顶堆还是小顶堆,假设我们用大顶堆(二叉树结构)我们每次更新时,都把树根弹出去(即最高),所以留下的都是小元素,所以我们要用小顶堆来解决这个问题:

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) {
        //运用map对元素出现频率进行一个统计
            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;

            for(unordered_map<int,int>::iterator it = map.begin();it!=map.end();it++){//对map中的所有元素进行遍历
                pri_que.push(*it);//对优先队列进行输入元素
                if(pri_que.size()>k){//如果大于k的部分,就弹出范围内中的最小值
                    pri_que.pop();
                }
            }
            //倒序回来,存储到result中
            vector<int> result(k);
            for(int i=k-1;i>=0;i--){
              result[i] = pri_que.top().first;
                pri_que.pop();//删除队列开头元素,释放内存
            }
            return result;
    }

};

end

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据引用\[1\],可以使用暴力解法来求解滑动窗口的最大。具体的做法是,遍历数组,对于每个窗口,使用一个内部循环来找到窗口中的最大,并将其存储在结果数组中。时间复杂度为O(n*k),其中n为数组长度,k为窗口大小。 根据引用\[2\],还可以使用队列来求解滑动窗口的最大。具体的做法是,使用一个双端队列来维护一个单调递减的窗口。遍历数组,对于每个元素,首先判断队头是否在滑动窗口范围内,如果不在,则将其从队头移除。然后,将当元素与队尾元素比较,如果当元素大于队尾元素,则将队尾元素移除,直到队列为空或者当元素小于等于队尾元素。最后,将当元素的索引插入队尾。如果滑动窗口元素个数达到了k个,并且始终维持在窗口中,就将队头元素加入答案数组中。时间复杂度为O(n),其中n为数组长度。 综上所述,可以使用暴力解法或者使用队列来求解leetcode滑动窗口的最大。 #### 引用[.reference_title] - *1* *3* [leetcode239. 滑动窗口最大](https://blog.csdn.net/kkkkuuga/article/details/124829581)[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^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode#239. 滑动窗口最大 (Java解法)](https://blog.csdn.net/paranior/article/details/114890555)[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^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值