【Leetcode 每日一题】面试题59 - II. 队列的最大值

题目描述

请定义一个队列并实现函数 max_value 得到队列里的最大值,要求函数max_value、push_back 和 pop_front 的时间复杂度都是O(1)。

若队列为空,pop_front 和 max_value 需要返回 -1

示例 1:

输入: 

["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]
[[],[1],[2],[],[],[]]

输出: 

[null,null,null,2,1,2]

示例 2:

输入: 

["MaxQueue","pop_front","max_value"]
[[],[],[]]

输出:

 [null,-1,-1]

限制:

  • 1 <= push_back,pop_front,max_value的总操作数 <= 10000
  • 1 <= value <= 10^5

思路一(暴力)

使用数组模拟一个队列的插入与删除,最大值通过遍历查找。

复杂度分析:

时间复杂度:O(1)(插入,删除),O(n)(求最大值)。
插入与删除只需要普通的队列操作,为 O(1),求最大值需要遍历当前的整个队列,最坏情况下为 O(n)。
空间复杂度:O(n),需要用队列存储所有插入的元素。

class MaxQueue {
public:
    int q[20000],begin=0,end=0;
    MaxQueue() {
    }
    
    int max_value() {
        int ans = -1;
        for(int i=begin;i<end;i++)
            ans = max(q[i],ans);
        return ans;
    }
    
    void push_back(int value) {
        q[end++]=value;
    }
    
    int pop_front() {
        if(begin==end)
            return -1;
        return q[begin++];
    }
};

思路二(单调递减双端队列)

使用普通队列处理pop返回,单调递减双端队列处理max返回。根据入队顺序,若为{1,3,2},再依次出队每次输出最大值,那么当3入队时,双端队列从尾端弹出1,因为为了存储最大值序列的双端队列中的1已经无效,无论如何3会比1后出队(先入先出原则),那么此时双端队列中仅有3;当2入队时,双端队列直接在后端插入2,因为2与尾端3比较较小,这样也能保证在1,3出队后,双端队列依然能够输出此时的最大值2。

复杂度分析:

时间复杂度:O(1)(插入,删除,求最大值)
删除操作于求最大值操作显然只需要 O(1)的时间。
而插入操作虽然看起来有循环,做一个插入操作时最多可能会有n次出队操作。但要注意,由于每个数字只会出队一次,因此对于所有的n个数字的插入过程,对应的所有出队操作也不会大于n次。因此将出队的时间均摊到每个插入操作上,时间复杂度为 O(1)。
空间复杂度:O(n),需要用队列存储所有插入的元素。

class MaxQueue {
public:
    queue<int> q;
    deque<int> d;
    MaxQueue() {
    }
    
    int max_value() {
        if(d.empty())
            return -1;
        return d.front();
    }
    
    void push_back(int value) {
        //依次出队尾部较小元素
        while(!d.empty() && d.back() < value)
            d.pop_back();
        d.push_back(value);
        q.push(value);
    }
    
    int pop_front() {
        if(q.empty())
            return -1;
        int ans = q.front();
        //出队的是最大值
        if(ans == d.front())
            d.pop_front();//递减双端队列头部弹出
        q.pop();
        return ans;
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值