码迷,mamicode.com
首页 > Windows程序 > 详细

【原创】leetCodeOj --- Sliding Window Maximum 解题报告

时间:2015-08-30 15:30:08      阅读:335      评论:0      收藏:0      [点我收藏+]

标签:

天,这题我已经没有底气高呼“水”了。。。

 

题目的地址:

https://leetcode.com/problems/sliding-window-maximum/

 

题目内容:

Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.

For example,
Given nums = [1,3,-1,-3,5,3,6,7], and k = 3.

Window position                Max
---------------               -----
[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

Therefore, return the max sliding window as [3,3,5,5,6,7].

Note: 
You may assume k is always valid, ie: 1 ≤ k ≤ input array‘s size for non-empty array.

Follow up:
Could you solve it in linear time?

 

题目解析:

关键是线性时间。开头我试图通过动态规划定义子问题来解决,然而这并没有什么卵用,怀疑自己已经患上了一定程度的动态规划病,需要重读CLRS回炉一番

其实有第二个关键点。均摊复杂度和严格复杂度,对于“线性时间内解决”这个要求而言,并没有什么不同的地方。

第三个关键点,就是这是一个动态维护的队列,你要在不重新遍历队中元素的情况下维护一个最值。

 

不知道各位是否做过O(1)时间内维护一个栈中最值的问题,如果没有,可以看看这篇老文:

【原创】leetCodeOj --- Min Stack 解题报告

 

那位说了,刚才还讲本质上是动态队列,现在你拿栈出来坑蒙拐骗,放学别走

别急别急,不是还能用栈模拟队列吗?

 

两个栈,队列的push操作,就把元素压到栈1。队列的pop操作,首先检查栈2是否非空,若栈2有元素,直接pop。若栈2无元素,则把当前栈1中全部的元素压进栈2。

 

这样,我们能够维护一个栈中的最值,就能维护一个队列中的最值。

因为当前队列中的全部元素都分布在这两个栈中,因此,这两个栈的最值再比一轮,就是最后的最值。

 

又有人问了,pop一次,栈2有东西还好,若没有,就得捣腾半天,把栈1的元素挨个压进栈2,这算哪门子线性时间?

 

还真是线性时间,别忘了均摊复杂度

每个元素,进队被压进一次栈1,出队时被压进栈2一次,算上弹出操作2次,一共只有4次操作。

一共n个元素

那就是4n个操作

不就是线性吗?

 

关键在于,一次实际的操作可能只有弹出一次,而压栈的操作被集成在某次弹出时集中执行了。

 

具体代码:

public class Solution {
    
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 0) {
            return nums;
        }
        int[] res = new int[nums.length - k + 1];
        MinQueue queue = new MinQueue();
        for (int i = 0; i < k; i ++) {
            queue.push(nums[i]);
        }
        res[0] = queue.getMax();
        int index = 1;
        for (int i = k; i < nums.length; i ++) {
            queue.pop();
            queue.push(nums[i]);
            res[index ++] = queue.getMax();
        }
        return res;
    }

    class MinQueue {
        
        LinkedList<Integer> stack1 = new LinkedList<Integer>();
        LinkedList<Integer> stack2 = new LinkedList<Integer>();
        LinkedList<Integer> maxOne = new LinkedList<Integer>();
        LinkedList<Integer> maxTwo = new LinkedList<Integer>();
        
        public void push(Integer item) {
            pushOne(item);
        }
        
        public Integer pop() {
            Integer res = null;
            if (stack2.size() == 0) {
                while (stack1.size() != 0) {
                    pushTwo(popOne());
                }
            }
            res = stack2.pop();
            maxTwo.pop();
            return res;
        }
        
        public Integer getMax() {
            Integer one = maxOne.peek();
            Integer two = maxTwo.peek();
            if (one == null) {
                return two;
            } else if (two == null){
                return one;
            }
            return one > two ? one : two;
        }
        
        private Integer popOne() {
            Integer res = null;
            maxOne.pop();
            res = stack1.pop();
            return res;
        }
        
        private void pushOne(Integer item) {
            stack1.push(item);
            if (stack1.size() == 1) {
                maxOne.push(item);
            } else {
                Integer front = maxOne.peek();
                if (front < item) {
                    maxOne.push(item);
                } else {
                    maxOne.push(front);
                }
            }
        }
        
        private void pushTwo(Integer item) {
            stack2.push(item);
            if (stack2.size() == 1) {
                maxTwo.push(item);
            } else {
                Integer front = maxTwo.peek();
                if (front < item) {
                    maxTwo.push(item);
                } else {
                    maxTwo.push(front);
                }
            }
        }
    }
    
}

 

【原创】leetCodeOj --- Sliding Window Maximum 解题报告

标签:

原文地址:http://www.cnblogs.com/shadowmydx/p/4770856.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!