剑指Offer59-II:队列最大值

题目: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%的用户,说明代码思路还不是最优。

原文地址:https://www.cnblogs.com/liuyongyu/p/14041596.html