(兩百三十一)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;
        }
    }

理解下了做法,當元素一個一個進入鏈表中時,由於是求最大值,所以比新進元素小的元素都沒有存在的必要,循環迭代會出現一個單調遞減隊列,隨着窗口的移動,最大值有可能被移除,當窗口每移動一格時,輸出鏈表的頭部,即當前窗口的最大值。

 

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