[LeetCode-239]滑动窗口最大值

题目链接:https://leetcode-cn.com/problems/sliding-window-maximum/


题目介绍:

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口 k 内的数字。滑动窗口每次只向右移动一位。

返回滑动窗口最大值。

示例:

[LeetCode-239]滑动窗口最大值_第1张图片
注意:

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

进阶:

你能在线性时间复杂度内解决此题吗?


解题思路:

一、暴力得天下

  • 通过两个for循环得出最大值
  • 外层for循环控制滑动窗口移动多少次
  • 内层for循环控制每次滑动窗口中的值
  • 每次在内层for循环中求出的最大值放入到数组并最后返回
public class Que239 {

    public int[] maxSlidingWindow(int[] nums, int k) {

        if (nums.length == 0 || k > nums.length){
            return new int[0];
        }

        int[] result = new int[nums.length - k + 1];

        int index = 0;

        for (int i = 0; i < nums.length - k; i++) {
            
            int max = nums[i];

            for (int j = i+1; j < k+i; j++) {
                if (max < nums[j]){
                    max= nums[j];
                }
            }
            
         result[index++] = max;
        }

        return result;
    }
    
    public static void main(String[] args) {
        int[] ints = new Que239().maxSlidingWindow(
                new int[]{1,3,-1,-3,5,3,6,7}
                ,3);
        System.out.println(ints);
    }
}

总结:
计算窗口的最大值需O(k),移动n-k+1次,时间复杂度为O(kn)


二、使用双端队列

  • 当每次需要往滑动窗口加入数的时候,判断滑动窗口内的是否小于要加入的,如果小于,就弹出
  • 在进行往加入数的时候,将左边的弹出
  • 队列的值是从大到小的,每次只需要取最左边的值即可
public class Que239 {

    public int[] maxSlidingWindow(int[] nums, int k) {

        if (nums == null || nums.length < 2){
            return nums;
        }
        
        //保存当前窗口最大值的数组位置
        LinkedList<Integer> queue = new LinkedList<Integer>();

        int[] result = new int[nums.length-k+1];

        for (int i = 0; i < nums.length; i++) {

            //保存从大到小,如果后面的比前面大,就依次弹出
            while (!queue.isEmpty() && nums[queue.peekLast()] < nums[i]){
                queue.pollLast();
            }

            queue.addLast(i);

            //如果当前队首是已移动窗口,则弹出
            if (queue.peek() <= i-k){
                queue.poll();
            }

            //当窗口长度为K时,保存结果
            if (i+1 >= k){
                result[i+1-k] = nums[queue.peek()];
            }
        }
        
        return result;
    }
    public static void main(String[] args) {
        int[] ints = new Que239().maxSlidingWindow(
                new int[]{1,3,-1,-3,5,3,6,7}
                ,3);
        System.out.println(ints);
    }
}

总结:
由于每个元素最多进队和出队各一次,因此该算法时间复杂度为O(N)。


代码地址:
https://github.com/Han-YLun/LeetCode/blob/master/Practice/src/Que239.java


文章为阿伦原创,如果文章有错的地方欢迎指正,大家互相交流。

你可能感兴趣的:(LeetCode,LeetCode239,阿伦的网络笔记)