I’ve read the Queue with min and max value code from Junmin Liu link. The one he mentioned is really good idea. It uses 2 stacks to keep the min/max for queue.
This problem is orignated from the count bound sliced problem. For that problem, I used another way to implement. By that, I can evolve it to another way of implementation queue with min/max. As I mentioned before, this min/max value is similar to the sliding window problem. Just evolve it with another min value.
I would say, both are good idea for queue with min/max.
2 queues solution should always change the queues more than 1 time operaiton. There is no constant O(1) time enqueue and dequeue.
2 stacks solution can always take O(1) time for enqueue and dequeue. But disadvantage is that there would be sometime that it takes O(n) for dequeue.
Here is my code:
- package util;
- import java.util.LinkedList;
- public class MQueue2 {
- private LinkedList<Integer> q = new LinkedList<Integer>();
- private LinkedList<Integer> maxq = new LinkedList<Integer>();
- private LinkedList<Integer> minq = new LinkedList<Integer>();
- public boolean enQueue(int e){
- enMaxq(e);
- enMinq(e);
- q.addLast(e);
- return true;
- }
- public int deQueue(){
- if(q.size()<1){
- return Integer.MIN_VALUE;
- }
- int curr = q.removeFirst();
- deMaxq(curr);
- deMinq(curr);
- return curr;
- }
- private void enMaxq(int e){
- if(maxq.size()==0){
- maxq.addLast(e);
- return;
- }
- int curr = maxq.getLast();
- while(e>curr&&maxq.size()>0){
- maxq.removeLast();
- if(maxq.size()<1){
- break;
- }
- curr = maxq.getLast();
- }
- maxq.addLast(e);
- }
- private void deMaxq(int e){
- if(maxq.size()<1){
- return;
- }
- int curr = maxq.getFirst();
- if(e==curr){
- maxq.removeFirst();
- }
- }
- private void enMinq(int e){
- if(minq.size()==0){
- minq.addLast(e);
- return;
- }
- int curr = minq.getLast();
- while(e<curr&&minq.size()>0){
- minq.removeLast();
- if(minq.size()<1){
- break;
- }
- curr = minq.getLast();
- }
- minq.addLast(e);
- }
- private void deMinq(int e){
- if(minq.size()<1){
- return;
- }
- int curr = minq.getFirst();
- if(e==curr){
- minq.removeFirst();
- }
- }
- public int min(){
- if(minq.size()<1){
- return Integer.MAX_VALUE;
- }
- return minq.getFirst();
- }
- public int max(){
- if(maxq.size()<1){
- return Integer.MIN_VALUE;
- }
- return maxq.getFirst();
- }
- }
I also attach Junmin Liu’s code:
- package util;
- import java.util.Stack;
- //a queue(FIFO) can track min and max of all elements in amortized O(1) time
- public class MQueue {
- MStack s_new = new MStack(), s_old = new MStack();
- public void enqueue(int i) {
- s_new.push(i);
- }
- public int dequeue() {
- if (s_old.isEmpty()) {
- while (!s_new.isEmpty()) {
- s_old.push(s_new.pop());
- }
- }
- return s_old.pop();
- }
- public boolean isEmpty() {
- return s_new.isEmpty() && s_old.isEmpty();
- }
- public int min() {
- return Math.min(s_new.min(), s_old.min());
- }
- public int max() {
- return Math.max(s_new.max(), s_old.max());
- }
- }
- // a stack node which contains min and max of all underlying elements
- class MNode {
- Integer i, min, max;
- MNode(int i, int max, int min) {
- this.i = i;
- this.max = max;
- this.min = min;
- }
- }
- // a stack(LIFO) can track min and max of all elements in amortized O(1) time
- class MStack {
- Stack<MNode> s = new Stack<MNode>();
- public boolean isEmpty() {
- return s.isEmpty();
- }
- public int min() {
- if (s.isEmpty())
- return Integer.MAX_VALUE;
- return s.peek().min;
- }
- public int max() {
- if (s.isEmpty())
- return Integer.MIN_VALUE;
- return s.peek().max;
- }
- public void push(int i) {
- int max = Math.max(i, max());
- int min = Math.min(i, min());
- s.push(new MNode(i, max, min));
- }
- public int pop() {
- System.out.println(s.peek().i);
- return s.pop().i;
- }
- }