Topic description:
Suppose there is such a queue with 3 operations:
a. EnQueue(v): add v to the queue;
b. DeQueue: delete the first element in the queue and return the second element;
c. MaxElement: Returns the largest element in the queue
Please design a data structure budget method to keep the time complexity of MaxElement operations as low as possible.
Solution one:
Create a new queue and traverse to get the maximum value. The time complexity is O(n).
public class Solution1 { public static void EnQueue(int v,Queue<Integer> a) { a.add(v); } public static int DeQueue(Queue<Integer> a) { int v = a.poll(); return v; } public static int MaxElement(Queue<Integer> a) { Queue<Integer> temp = new LinkedList<>(); int max = a.peek(); while(a.poll()!=null) { int v = a.poll(); if(v > max) max = v; temp.add(v); } return max; } public static void main(String[] args) { Queue<Integer> a = new LinkedList<>(); EnQueue(1, a); EnQueue(4, a); System.out.println(DeQueue(a)); EnQueue(5, a); EnQueue(1, a); EnQueue(2, a); System.out.println(MaxElement(a)); } }
A little improvement can be made here, adding a comparison process to EnQueue(v), so that a new queue is not needed.
import java.util.LinkedList; import java.util.Queue; public class Solution1 { public static int EnQueue(int max,int v,Queue<Integer> a) { a.add(v); if(v > max) max = v; return max; } public static int DeQueue(Queue<Integer> a) { int v = a.poll(); return v; } public static void MaxElement(int max) { System.out.println(max); } public static void main(String[] args) { Queue<Integer> a = new LinkedList<>(); int max = 1; max = EnQueue(max,1, a); max = EnQueue(max,4, a); System.out.println(DeQueue(a)); max = EnQueue(max,5, a); max = EnQueue(max,1, a); max = EnQueue(max,2, a); MaxElement (max); } }
Solution two:
Use a max heap to maintain the elements in the queue. The time complexity is O(1), and the space complexity is O(logn).
Solution three:
Maintaining a sequence of maximum values guarantees that the time complexity of the Max operation is O(1). The stack is used to implement the queue, and the Max operation of the stack is relatively easy to implement.
public class Solution3 { public static void main(String[] args) { //Define a Stack class Stack s = new Stack(5); s.push(12); s.push(3); s.push(5); s.push(9); s.push(6); s.push(36); System.out.println(s.Max()); s.Pop(); System.out.println(s.Max()); //Define a Queue_T class, implemented with Stack Queue_T q = new Queue_T(); q.EnQueue(3); q.EnQueue(4); q.EnQueue(2); System.out.println(q.Max()); q.DeQueue(); q.EnQueue(5); System.out.println(q.Max()); } private static class Stack { private static int maxStackItemIndex; private static int stackTop; private static int[] link2NextMaxItemm; //Maximum sequence private static int[] stackItem; private static int maxn; public Stack(int maxn) { stackTop = -1; maxStackItemIndex = -1; link2NextMaxItenm = new int[maxn]; stackItem = new int[maxn]; this.maxn = maxn; } void push(int x) { if (stackTop >= maxn-1) {} //Exceeds the maximum storage capacity of the stack else { stackTop++; stackItem[stackTop] = x; if (x > Max()) { link2NextMaxItenm [stackTop] = maxStackItemIndex; maxStackItemIndex = stackTop; } else { link2NextMaxItenm[stackTop] = -1; } } } int Pop(){ int ret; if(stackTop <0){ return -1; }else{ ret = stackItem[stackTop]; if(stackTop == maxStackItemIndex){ maxStackItemIndex = link2NextMaxItenm [stackTop]; } stackTop--; return ret; } } int Max() { if (maxStackItemIndex >= 0) { return stackItem[maxStackItemIndex]; } else { return -1; } } } }
Queue_T class:
import java.util.Enumeration; class Queue_T{ private java.util.Stack <Integer> stackA; private java.util.Stack<Integer> stackB; private int max_index; public Queue_T() { stackA = new java.util.Stack <Integer> (); stackB = new java.util.Stack<Integer>(); max_index = -1; } void EnQueue(int v) { stackB.push(v); if(v > max_index) { max_index = v; } } Integer DeQueue() { if(stackA.isEmpty()) { while(!stackB.isEmpty()) { stackA.push(stackB.pop()); } } int peek = stackA.pop(); if(peek == max_index) { max_index = LookMax(); } return peek; } int Max() { return max_index; } int LookMax() { int maxA = -1; int maxB = -1; Enumeration<Integer> itemsA = stackA.elements(); while(itemsA.hasMoreElements()) { if(itemsA.nextElement() > maxA) { maxA = itemsA.nextElement(); } } if(!stackB.isEmpty()) { Enumeration<Integer> itemsB = stackB.elements(); while(itemsB.hasMoreElements()) { if(itemsB.nextElement() > maxB) { maxB = itemsB.nextElement(); } } } if(maxA > maxB) return maxA; else return maxB; } }