🚩传送门:力扣题目

题目

请定义一个队列并实现函数 [LC]59. 队列的最大值 - 图1 得到队列里的最大值,要求函数 [LC]59. 队列的最大值 - 图2[LC]59. 队列的最大值 - 图3[LC]59. 队列的最大值 - 图4 的均摊时间复杂度都是[LC]59. 队列的最大值 - 图5

若队列为空,[LC]59. 队列的最大值 - 图6[LC]59. 队列的最大值 - 图7 需要返回 [LC]59. 队列的最大值 - 图8

示例 1:

输入: [“MaxQueue”,”push_back”,”push_back”,”max_value”,”pop_front”,”max_value”][[],[1],[2],[],[],[]] 输出: [null,null,null,2,1,2]

解题思路:单调双端队列

如下图所示,考虑构建一个 递减列表 来保存队列 所有递减的元素 ,递减链表随着入队和出队操作实时更新,这样队列最大元素就始终对应递减列表的首元素,实现了获取最大值 [LC]59. 队列的最大值 - 图9 时间复杂度。
[LC]59. 队列的最大值 - 图10

复杂度分析

时间复杂度:[LC]59. 队列的最大值 - 图11,函数 [LC]59. 队列的最大值 - 图12[LC]59. 队列的最大值 - 图13[LC]59. 队列的最大值 - 图14 的均摊时间复杂度都是[LC]59. 队列的最大值 - 图15

空间复杂度:[LC]59. 队列的最大值 - 图16,当元素个数为 [LC]59. 队列的最大值 - 图17 时,最差情况下 deque 中保存 [LC]59. 队列的最大值 - 图18 个元素;

我的代码

  1. class MaxQueue {
  2. LinkedList<Integer> resQueue = null;
  3. LinkedList<Integer> maxQueue = null;
  4. public MaxQueue() {
  5. resQueue = new LinkedList<>();
  6. maxQueue = new LinkedList<>();
  7. }
  8. public int max_value() {
  9. if (!maxQueue.isEmpty()) return maxQueue.peekFirst();
  10. return -1;
  11. }
  12. public void push_back(int value) {
  13. // resQueue添加当前值
  14. resQueue.addLast(value);
  15. if (maxQueue.isEmpty()) {
  16. // 最大队列空,直接添加
  17. maxQueue.addLast(value);
  18. } else if (value > maxQueue.peekFirst()) {
  19. // value大于最大值,直接清空,添加当前元素
  20. maxQueue.clear();
  21. maxQueue.addLast(value);
  22. } else if (value < maxQueue.peekLast()) {
  23. // 小于最小值
  24. maxQueue.addLast(value);
  25. } else {
  26. // 移除中间值
  27. while (!maxQueue.isEmpty() && maxQueue.peekLast() < value) {
  28. maxQueue.pollLast();
  29. }
  30. // maxQueue添加当前值
  31. maxQueue.addLast(value);
  32. }
  33. }
  34. public int pop_front() {
  35. if (!resQueue.isEmpty()) {
  36. int pop = resQueue.pollFirst();
  37. if (maxQueue.peekFirst() == pop)
  38. maxQueue.pollFirst();
  39. return pop;
  40. }
  41. return -1;
  42. }
  43. public static void main(String[] args) {
  44. MaxQueue mq = new MaxQueue();
  45. }
  46. }