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

文章目录

      • 题目
      • 暴力解法
        • 思路
        • 复杂度分析
        • 实现
      • 单调的双端队列解法
        • 思路
        • 复杂度分析
        • 实现
      • C++复习
        • std::queue常用操作复习
        • std::deque常用操作复习
      • 参考

题目

题目链接[LeetCode每日1题][中等] 面试题59 - II. 队列的最大值_第1张图片

暴力解法

思路

这题最开始想到的是暴力法,用一个队列+一个数组实现。因为数据范围在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() 返回队尾元素

参考

官方题解

你可能感兴趣的:([LeetCode每日1题][中等] 面试题59 - II. 队列的最大值)