剑指 Offer 59 - I. 滑动窗口的最大值、II. 队列的最大值

剑指 Offer 59 - I. 滑动窗口的最大值

在这里插入图片描述

解法

使用一个双端队列,头部保存当前滑动窗口的最大值。依次将数字从尾部加入队列,如果该数字比该队列尾部数字大则将队列尾部数字去除。如果如果当前处理的数字下标与队列头部数字的下标差值大于等于3,表明该最大数字已经滑出窗口,那么删除队列头部数字。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k < 1) return new int[]{};
        // 使用ArrayList, LinkedList 查询太慢
        List<Integer> maxInWindows = new ArrayList<>();
        Deque<Integer> index = new LinkedList<>();
        for (int i = 0; i < k; i++) {
            while (!index.isEmpty() && nums[i] > nums[index.peekLast()])
                index.pollLast();
            index.offerLast(i);
        }
        for (int i = k; i < nums.length; ++i) {
            maxInWindows.add(nums[index.peekFirst()]);
            while (!index.isEmpty() && nums[i] > nums[index.peekLast()])
                index.pollLast();
            while(!index.isEmpty() && index.peekFirst() <= (i - k))
                index.pollFirst();
            index.offerLast(i);
        }
        maxInWindows.add(nums[index.peekFirst()]);
        int[] ans = new int[maxInWindows.size()];
        for (int i = 0; i < ans.length; i++) {
            ans[i] = maxInWindows.get(i);
        }
        return ans;
    }
}

剑指 Offer 59 - II. 队列的最大值

在这里插入图片描述

解法

与上题类似,可以使用一个双端队列保存当前队列的最大值,使用另一个队列当作普通队列。保存最大值的队列头部始终就是最大值。当普通队列弹出元素的下标与,最大值队列头部元素下标相同时,需要将最大队列的元素也去除。

class MaxQueue {

    class InternalData {
        int number;
        int index;
        InternalData(int number, int index) {
            this.number = number;
            this.index = index;
        }
    }

    private int currentIndex = 0;

    private Deque<InternalData> data;
    private Deque<InternalData> max;

    public MaxQueue() {
        this.data = new LinkedList<>();
        this.max = new LinkedList<>();
    }
    
    public int max_value() {
        if (max.isEmpty()) return -1;
        return max.peekFirst().number;
    }
    
    public void push_back(int value) {
        while (!max.isEmpty() && value > max.peekLast().number)
            max.pollLast();
        max.offerLast(new InternalData(value, currentIndex));
        data.offerLast(new InternalData(value, currentIndex));
        ++currentIndex;
    }
    
    public int pop_front() {
        if(max.isEmpty()) return -1;
        InternalData first = data.pollFirst();
        if (first.index == max.peekFirst().index) {
            max.pollFirst();
        }
        return first.number;
    }
}

/**
 * Your MaxQueue object will be instantiated and called as such:
 * MaxQueue obj = new MaxQueue();
 * int param_1 = obj.max_value();
 * obj.push_back(value);
 * int param_3 = obj.pop_front();
 */
posted @ 2020-09-23 10:55  消灭猕猴桃  阅读(66)  评论(0编辑  收藏  举报