题目:https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/
题意:实现一个队列接口,使它能够在o(1)时间内获取队列中的最大值
思路:双端队列。因为队列存在入队和出队的操作,所以队列中的最大值不是固定的。队列含有先进先出的特性,所以当一个元素入队后,当该元素是队列中的最大值,那么可以不考虑该最大值之前的元素,因为它们会比该元素早出队。因此,我们维护一个双端队列,每次元素入队时,先与队头元素比较,大于队头元素时,就替换队头元素;否则,与双端队列的队尾元素进行比较,当大于队尾元素时就出队,直到不大于队尾元素,将该元素入队。
代码:
public class Offer59 { private LinkedList<Integer> maxValue; private int[] queue; private int front, back; private final static int MAX_LENGTH = 10001; public Offer59() { queue = new int[MAX_LENGTH]; front = back = 0; maxValue = new LinkedList<>(); } public int max_value() { if(front == back) return -1; return queue[maxValue.peekFirst()]; } public void push_back(int value) { queue[back] = value; if(maxValue.isEmpty()) { maxValue.offerLast(back); } else { if(value >= queue[maxValue.peekFirst()]){ maxValue.clear(); maxValue.offerLast(back); }else{ while (value > queue[maxValue.peekLast()]) { maxValue.pollLast(); } maxValue.offerLast(back); } } back = ((back+1) % MAX_LENGTH); } public int pop_front() { if(front == back) return -1; int t = queue[front]; front = (front + 1) % MAX_LENGTH; if (maxValue.peekFirst() < front) { maxValue.pollFirst(); } return t; } public static void main(String...args){ Offer59 offer59 = new Offer59(); offer59.push_back(5); System.out.println(offer59.max_value()); offer59.push_back(1); System.out.println(offer59.max_value()); offer59.push_back(2); System.out.println(offer59.max_value()); System.out.println(offer59.pop_front()); System.out.println(offer59.max_value()); System.out.println(offer59.pop_front()); System.out.println(offer59.pop_front()); System.out.println(offer59.pop_front()); System.out.println(offer59.max_value()); offer59.push_back(4); System.out.println(offer59.pop_front()); System.out.println(offer59.max_value()); System.out.println(offer59.max_value()); } }
ps:题目中操作次数在[1, 10000]内,因此开了个整型数组作为队列,最后的内存消耗打败了92.46%的用户,说明这样做还是可以的。但时间消耗只打败了26.95%的用户,说明代码思路还不是最优。