Medium | 剑指 Offer 59

剑指 Offer 59 - II. 队列的最大值

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

若队列为空,pop_frontmax_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

解体思路

此题与Hard | LeetCode 239 | 剑指 Offer 59 - I. 滑动窗口的最大值 是一样的, 区别在于前一道题是窗口的大小限制让元素不得不出队, 而这道题他是随时都可以出队, 也随时可以不出队。所以解法都是一样, 使用一个辅助的单调递减队列记录可能成为最大值的元素。不过这里就不能存下标了, 直接存值。如果出队的元素恰好是单调队列的队首元素, 那么单调队列队首元素也必须出队。

class MaxQueue {

    // 用于存储所有数据队列
    private Deque<Integer> queue;
    // 单调递减队列, 用以存储可能成为队列最大值的元素
    private Deque<Integer> monotonicQueue;

    public MaxQueue() {
        queue = new ArrayDeque<>();
        monotonicQueue = new ArrayDeque<>();
    }
    
    // 需要实现的方法 获取队列里的最大值
    public int max_value() {
        if (!monotonicQueue.isEmpty()) {
            return monotonicQueue.peek();
        }
        return -1;
    }
    
    // 需要实现的方法 队列入队元素
    public void push_back(int value) {
        queue.add(value);
        while (!monotonicQueue.isEmpty()) {
            int val = monotonicQueue.getLast();
            if (value > val) {
                monotonicQueue.removeLast();
            } else {
                break;
            }
        }
        monotonicQueue.add(value);
    }
    
    // 需要实现的方法 队首元素出队
    public int pop_front() {
        if (!queue.isEmpty()) {
            int head = queue.poll();
            if (head == monotonicQueue.peek()) {
                monotonicQueue.poll();
            }
            return head;
        }
        return -1;
    }
}
原文地址:https://www.cnblogs.com/chenrj97/p/14282164.html