leetcode239. 滑动窗口最大值(java详解)

一:题目

leetcode239. 滑动窗口最大值(java详解)_第1张图片

二:思路

1:lc通过版


class Solution {
    /*
        思路:1.这里是要求出每一个窗口中的最大值,那么我们自然的想到如何用一个队列 可以使其每次队首
               出现最大值,那么我自然回想到大顶堆,但是用了之后,我们窗口中的元素位置就发生了变化
               那么当我们移动窗口的时候,就不能正确的 pop出窗口的首个元素。
             2.那么这里的话,我们就自定义一个队列,当然的话,让其满足每次pop出去的最大的元素
                那么其和优先队列有何区别呢?  
                区别就在于push()上 我们push的时候,如果发现队尾元素是比其小的话,那么我们就其pop了
                如果队尾元素比其大的话,我们就push进去。
                那么我们每次移动的时候 队首就是最大值,直接访问即可,并将其移出对列;
                如果队首不是最大值的话,那么我们就不用pop了,这个时候其实队列中的元素的是不满足k个的
                因为我们每次push的时候只是push进去 元素的相对位置 比起小的我们都pop了
            3.关于我们使用的这个数据结构我们也应该有所了解
                Deque deque = new LinkedList<>();
                - 这是个双端数组
                - 队首的话 我们可以访问队首元素,也可以删除队首元素
                    访问队首:deque.peek();
                    删除队首元素:deque.poll();
                - 队尾的话 我们也可以访问,并且可以删除和添加
                    访问队尾元素: deque.getLast();
                    删除队尾元素:deque.removeLast();
                    在队尾添加元素:deque.add(x);    
    */


    public int[] maxSlidingWindow(int[] nums, int k) {
        
        if (nums.length == 1) return nums;

        MyQueue queue = new MyQueue();

        int len = nums.length - k + 1;//代数求出
        int[] ans = new int[len];
        int index = 0;

        for (int i = 0; i < k; i++) {
            queue.add(nums[i]);
        }

        ans[index++] = queue.peek();

        for (int i = k; i < nums.length; i++) {
            //移除队列 首个元素 可能最大值就是首部元素,也可能不是
            queue.poll(nums[i-k]);
            //添加新元素
            queue.add(nums[i]);
            ans[index++] = queue.peek();
        }


        return ans;
    }
}


class MyQueue{

    Deque<Integer> deque = new LinkedList<>();
    
    //poll元素的的话,当前的这个数组是否为空,还有的就是当前队首元素是否为该窗口的最大值,如果是就移除
    //如果不是最大值的话,那么该滑动窗口中的元素的个数是不够k个的(因为我只是记录元素的相对位置)
    public void poll(int val) {
        if (!deque.isEmpty() && deque.peek() == val) {//队首元素
            deque.poll();
        }
    } 

    //在队尾添加元素
    //得判断队列中的尾部元素 tail 跟我们的要插入的值 insert 大小关系
    // tail < insert 那么的话 我们就移除队列尾部元素
    // tail > insert 那么的话 我们就正常添加
    public void add(int val) {
        while (!deque.isEmpty() && val > deque.getLast()) {//比队尾元素大的话
            deque.removeLast();
        }   
        deque.add(val);//比队尾元素小的话
    }

    //访问首部元素
    public int peek() {        
        return deque.peek();
    }


}

2:lc超时版

class Solution {
    /*
        思路:1.这里是要求出每一个窗口中的最大值,那么我们自然的想到如何用一个队列 可以使其每次队首
               出现最大值。

    */

    public int max(int[] segment,int n) {
        int maxx = -999999;
        for (int i = 0; i < n; i++) {
            if (maxx < segment[i]) {
                maxx = segment[i];
            }
        }
        return maxx;
    }

    public int[] maxSlidingWindow(int[] nums, int k) {
        
        int len = nums.length-k+1;//代数求解
        int[] ans = new int[len];
        int ansIndex = 0;

        for (int i = 0; i < len; i++) {
            int[] temp = new int[k];
            int tempIndex = 0;
            int count = 0;
            int j = i;

            while (count != k) {
                temp[tempIndex++] = nums[j++];
                count++;
            }

            int eachAns = max(temp,k);
            ans[ansIndex++] = eachAns;
        }

        return ans;

    }
}

你可能感兴趣的:(算法分析与设计,leetcode复习题目,java,leetcode,数据结构)