您的位置:首页 > 职场人生

[LeetCode每日1题][中等] 面试题59 - II. 队列的最大值

2020-03-11 13:08 543 查看

文章目录

  • 单调的双端队列解法
  • C++复习
  • 参考
  • 题目

    题目链接

    暴力解法

    思路

    这题最开始想到的是暴力法,用一个队列+一个数组实现。因为数据范围在1~105之间,可以用类似于桶排序的思路,插入或删除元素时在数组对应下标元素+1/-1。

    复杂度分析

    插入和删除的为复杂度O(1)。但是选取最大值的时候,需要从数组末端往前遍历,如果发现值大于0,则是我们要的最大值。这样,最多需要遍历105个元素,最少遍历1个。复杂度显然达不到O(1)的要求。

    后来发现直接用数组滑动窗口(begin和end标记位)实现队列,需要最大值时直接遍历数组就好。真是太久没做题了Orz。

    实现

    class MaxQueue {
    int q[20000];
    int begin = 0, end = 0;
    public:
    MaxQueue() {
    }
    
    int max_value() {
    int ans = -1;
    for (int i = begin; i != end; ++i)
    ans = max(ans, q[i]);
    return ans;
    }
    
    void push_back(int value) {
    q[end++] = value;
    }
    
    int pop_front() {
    if (begin == end)
    return -1;
    return q[begin++];
    }
    };
    
    作者:LeetCode-Solution
    链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/mian-shi-ti-59-ii-dui-lie-de-zui-da-zhi-by-leetcod/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    单调的双端队列解法

    思路

    当一个元素进入队列时,它前面所有比它小的元素都不会再对答案产生影响。维护一个双端队列deque,插入一个元素时,从后往前遍历,如果比待插入元素小,出队,直到遇到发现一个不小于待插入元素的元素。这样就保证了队列的单调递减。

    复杂度分析

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

    实现

    class MaxQueue {
    queue<int> q;
    deque<int> d;
    public:
    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;
    }
    };
    
    作者:LeetCode-Solution
    链接:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/solution/mian-shi-ti-59-ii-dui-lie-de-zui-da-zhi-by-leetcod/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    C++复习

    std::queue常用操作复习

    函数签名 作用
    void std::queue::push(T) 将元素插入队尾
    void std::queue::pop() 将队首元素移出队列
    T std::queue::front() 返回队首元素
    T std::queue::back() 返回队尾元素

    std::deque常用操作复习

    函数签名 作用
    void std::deque::push_front(T) 将元素插入队头
    void std::deque::push_back(T) 将元素插入队尾
    void std::deque::pop_front() 将队首元素移出队列
    void std::deque::pop_back() 将队尾元素移出队列
    T std::deque::front() 返回队首元素
    T std::deque::back() 返回队尾元素

    参考

    官方题解

    • 点赞
    • 收藏
    • 分享
    • 文章举报
    EvergIow 发布了3 篇原创文章 · 获赞 0 · 访问量 54 私信 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: