(两百三十一)leetcode 滑动窗口的最大值

1.题目

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 
解释: 

  滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7
 

提示:

你可以假设 k 总是有效的,在输入数组不为空的情况下,1 ≤ k ≤ 输入数组的大小。

注意:本题与主站 239 题相同:https://leetcode-cn.com/problems/sliding-window-maximum/

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

2.思路

感觉没什么好的思路,主要就是比较前k个中最大的那个,然后出栈一下,再比较前k个最大的那个,第一次比较的结果很有用,后续的比较需要依赖第一次比较的结果,然后数组其实是和队列一样的是先进先出,然后还要比较当前队列的最大值,然后我结合了化栈为队和栈获取最大值的自定义实现写的。。。

 

3.coding

    class Solution {
        public int[] maxSlidingWindow(int[] nums, int k) {
            if(nums.length == 0){
                return new int[]{};
            }
            int[] maxs = new int[nums.length - k + 1];
            MyQueue myQueue = new MyQueue();
            for (int i = 0; i + k <= nums.length; i++) {
                if (i == 0) {
                    for (int j = 0; j < k; j++) {
                        myQueue.push(nums[j]);
                    }
                } else {
                    myQueue.pop();
                    myQueue.push(nums[i + k - 1]);
                }
                maxs[i] = myQueue.getMax();
            }
            return maxs;
        }


        class MyQueue {
            MaxStack popStack = new MaxStack();
            MaxStack pushStack = new MaxStack();

            /**
             * Initialize your data structure here.
             */
            public MyQueue() {

            }

            /**
             * Push element x to the back of queue.
             */
            public void push(int x) {
                pushStack.push(x);
            }

            /**
             * Removes the element from in front of queue and returns that element.
             */
            public int pop() {
                transtion();
                return popStack.pop();
            }

            private void transtion() {
                if (popStack.isEmpty()) {
                    while (!pushStack.isEmpty()) {
                        popStack.push(pushStack.pop());
                    }
                }
            }

            /**
             * Get the front element.
             */
            public int peek() {
                transtion();
                return popStack.peek();
            }

            /**
             * Returns whether the queue is empty.
             */
            public boolean empty() {
                return popStack.isEmpty() && pushStack.isEmpty();
            }

            public int getMax() {
                if (popStack.isEmpty()) {
                    return pushStack.getMax();
                } else if (pushStack.isEmpty()) {
                    return popStack.getMax();
                } else {
                    return popStack.getMax() > pushStack.getMax() ? popStack.getMax() : pushStack.getMax();
                }
            }
        }

        class MaxStack {
            Stack<Integer> stack = new Stack();
            Stack<Integer> maxStack = new Stack();

            /**
             * initialize your data structure here.
             */
            public MaxStack() {

            }

            public void push(int x) {
                stack.push(x);
                if (maxStack.isEmpty()) {
                    maxStack.push(x);
                } else if (x >= maxStack.peek()) {
                    maxStack.push(x);
                }
            }

            public int pop() {
                if (!stack.isEmpty()) {
                    int x = stack.pop();
                    if (x == maxStack.peek()) {
                        maxStack.pop();
                    }
                    return x;
                }
                throw new RuntimeException("pop for none");
            }

            public int peek() {
                return stack.peek();
            }

            public int getMax() {
                return maxStack.peek();
            }

            public boolean isEmpty() {
                return stack.isEmpty();
            }
        }
    }

看解答发现这题对应于hard难度,你这简单难度对应hard难度还玩不玩啊。。。我说怎么这么难写

注意:本题与主站 239 题相同:https://leetcode-cn.com/problems/sliding-window-maximum/

参考答案

    class Solution {
        public int[] maxSlidingWindow(int[] nums, int k) {
            if(nums == null || nums.length == 0 || k == 0){
                return new int[0];
            }

            LinkedList<Integer> linkedList = new LinkedList<Integer>();
            int[] res = new int[nums.length - k + 1];
            for(int i = 0; i < nums.length; i++) {
                while (!linkedList.isEmpty()
                        && nums[i] > nums[linkedList.peekLast()]) {
                    linkedList.removeLast();
                }
                linkedList.add(i);
                if (i - k >= 0 && linkedList.getFirst() == i - k){
                    linkedList.removeFirst();
                }

                if (i - k + 1 >= 0){
                    res[i - k + 1] = nums[linkedList.getFirst()];
                }
            }
            return res;
        }
    }

理解下了做法,当元素一个一个进入链表中时,由于是求最大值,所以比新进元素小的元素都没有存在的必要,循环迭代会出现一个单调递减队列,随着窗口的移动,最大值有可能被移除,当窗口每移动一格时,输出链表的头部,即当前窗口的最大值。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章