编程之美3.7:队列中取最大值操作问题

题目描述:
假设有这样一个拥有3个操作的队列:
a. EnQueue(v):将v加入队列中;
b. DeQueue:使队列中的队首元素删除并返回次元素;
c. MaxElement:返回队列中的最大元素

请设计一种数据结构预算法,让MaxElement操作的时间复杂度尽可能低。

解法一:
新建一个队列,然后遍历取得最大值。时间复杂度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));		
	}
}

这里可以做一点改进,在EnQueue(v)中加入比较过程,从而不用重新新建一个队列。
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);		
	}
}

 
 
解法二:
用最大堆来维护队列中的元素。时间复杂度O(1),空间复杂度O(logn)。
解法三:
维护一个最大值序列保证Max操作的时间复杂度是O(1)。用栈实现队列,栈的Max操作比较容易实现。
 
  
public class Solution3 {
		  
	    public static void main(String[] args) {  
	        //定义一个Stack类  
	        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());  
	        //定义一个Queue_T类,用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[] link2NextMaxItenm; //最大值序列 
	        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) {} //超出栈的最大存储量
	            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类:
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;
	}
}



猜你喜欢

转载自blog.csdn.net/weixin_41876155/article/details/80039874