题目描述:
假设有这样一个拥有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; } }