图解LeetCode——剑指 Offer 59 - II. 队列的最大值

简介: 图解LeetCode算法

一、题目

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

二、示例

2.1> 示例 1:

输入】 ["MaxQueue","push_back","push_back","max_value","pop_front","max_value"]

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

输出】 [null,null,null,2,1,2]

2.2> 示例 2:

输入】 ["MaxQueue","pop_front","max_value"]

[[],[],[]]

输出】 [null,-1,-1]

限制:

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

三、解题思路

根据题目描述,我们需要提供如下3个方法:

max_value】当前队列中的最大值;

push_back】向队列末尾添加元素;

pop_front】从队列头获取元素;

其中,如果假设题目中只要求实现push_back方法和pop_front方法的话,那么本题我们就会非常的简单,就是实现一个简单的队列即可。

而其中比较棘手的就是max_value方法的实现,因为它表示的是当前队列中的最大值。那么我们针对这个最大值,首先会想到两种方式来实现:

方式1】初始化max变量,然后每当插入一个元素的时候更新max值,即:max=Math.max(max, value) 而这种做法的问题就在于,如果这个最大值出队列了,那么当前队列的最大值就变化了。很显然,不满足题目需求。

方式2】创建一个集合,每次插入元素的时候,都对其进行排序操作。这种很显然是满足题目要求的,但是明显时间复杂度和空间复杂度都不高。

那么有没有更好的解决办法呢?其实我们可以考虑一个例子,假设我们要分别插入1,7,2这3个数:

插入数字1】当前最大值为1

插入数字7】当前最大值为7

插入数字2】当前最大值为7

移除数字1】当前最大值为7

移除数字7】当前最大值为2

从上面的规律中,我们可以看到,无论移除任意元素,最大值都不会是1,原因就是数字1肯定是先于数字7被移除掉了。所以,我们可以采用双向队列结构deque,再根据以下规律,来维护当前最大值:

情况1】如果deque为空,则直接执行插入操作;

情况2】如果deque的末尾元素A小于 待插入元素B,那么元素A出队列;

情况3】如果deque的末尾元素A大于等于 待插入元素B,那么元素B出队列;

解题思路就如上面所述,下面我们还是按照惯例,举例演示:我们要插入数字1,7,2,4;我们来看一下具体的存储方式。请见下图所示:

四、代码实现

class MaxQueue {
    int[] queue;
    int head = 0, tail = 0;
    Deque<Integer> deque = new ArrayDeque();
    public MaxQueue() {
        queue = new int[10000];
    }
    public int max_value() {
        return deque.peekFirst() == null ? -1 : deque.peekFirst();
    }
    public void push_back(int value) {
        queue[tail++] = value;
        if (deque.isEmpty() || deque.peekLast() >= value) {
            deque.addLast(value);
            return;
        }
        while (!deque.isEmpty() && deque.peekLast() < value) deque.removeLast();
        deque.addLast(value);
    }
    public int pop_front() {
       int num = queue[head] == 0 ? -1 : queue[head++];
       if (!deque.isEmpty() && deque.peekFirst() == num) deque.removeFirst();
       return num;
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」


相关文章
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
52 6
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
44 4
|
21天前
【LeetCode 24】225.用队列实现栈
【LeetCode 24】225.用队列实现栈
9 0
|
22天前
|
算法
【LeetCode 23】232.用栈实现队列
【LeetCode 23】232.用栈实现队列
15 0
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
24 4
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
49 5
|
3月前
|
算法 Python
【Leetcode刷题Python】剑指 Offer 33. 二叉搜索树的后序遍历序列
本文提供了一种Python算法,用以判断给定整数数组是否为某二叉搜索树的后序遍历结果,通过识别根节点并递归验证左右子树的值是否满足二叉搜索树的性质。
21 3
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - II. 从上到下打印二叉树 II
本文提供了一种Python实现方法,用于层次遍历二叉树并按层打印结果,每层节点按从左到右的顺序排列,每层打印到一行。
35 3
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
Leetcode题目"剑指 Offer 21. 调整数组顺序使奇数位于偶数前面"的两种Python解决方案,一种是使用双端队列调整数组顺序,另一种是使用双指针法将奇数移到数组前半部分,偶数移到后半部分。
27 4
|
3月前
|
Python
【Leetcode刷题Python】剑指 Offer 18. 删除链表的节点
Leetcode题目"剑指 Offer 18. 删除链表的节点"的Python解决方案,通过使用双指针法找到并删除链表中值为特定数值的节点,然后返回更新后的链表头节点。
40 4