• 【每日一题-leetcode】239.滑动窗口最大值


    239.滑动窗口最大值

    1. 滑动窗口最大值

    难度困难290

    给定一个数组 nums,有一个大小为 k *的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 *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
    

    1.暴力法

    思路:我们可以将滑动窗口问题抽象化,一直移动那么最后的数据格式就是一个二维数组 for for 遍历找出每次滑动窗口的最大值存储起来,就可以了。首先是确定滑动窗口的次数。k是窗口的大小,n是长度 k = 3 n = 8 移动了6 size = n - k +1 外层循环是移动次数 内层循环开始条件是 i 随着移动次数增加, k = i 终止条件为 最终移动的次数 i + k 就到数组的最后了。剩下依次判断就可以了。

    时间复杂度:O(N*K) 外层k次 内层N次

    空间复杂度:O(n-k+1)

       public int[] maxSlidingWindow(int[] nums, int k) {
                //参数判断
                int length = nums.length;
                if(length * k == 0){
                    return new int [0];
                }
                //窗口移动的次数为length-k+1
                int [] array = new int [length-k+1];  
                for(int i=0;i<length-k+1;i++){
                    int max = Integer.MIN_VALUE;
                  //因为窗口每次都要移动 在i的基础上 增加 终止条件是i+k 说明到底
                  //每一次loop 找出最大值
                    for(int j=i;j<i+k;j++){
                        max = Math.max(max,nums[j]);
                    }
                   //该层的最大值
                    array[i] = max;
                }
                return array;
            }
    

    2.双端队列

    思路:使用队列进行存储每次窗口的最大值的下标,如果当前值最大 那么之前的所有值就可以清空了

    ps : 1 3 4 4最大 所以在这个窗口期中4一直最大 1 3 就可以出队列。

    time:O(N) 队列的出队和入队是O(1) 只存在遍历n次数组中的数据

    space:O(n)

    private  ArrayDeque<Integer> deq = new ArrayDeque();//存储下标值 比较大小
    private  int [] nums;
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums.length == 0 || k == 0){ //参数判断
            return new int [0];
        }
        int n = nums.length;   this.nums = nums;
        //存储最大值的数组
        int [] arr = new int [n-k+1];   int maxIndex = 0;
        for(int i=0;i<k;i++){
            cleanDeq(i,k);
            deq.addLast(i);
            maxIndex = nums[maxIndex] > nums[i] ? maxIndex : i;  
       }
        arr[0] = nums[maxIndex];
        for(int i = k;i<n;i++){
            cleanDeq(i,k);
            deq.addLast(i);
            arr[i-k+1] = nums[deq.getFirst()];
        }
        return arr;
    }
    public void cleanDeq(int i,int k){
        if(!deq.isEmpty() && deq.getFirst() == i-k){//删除前边数据较小的。或者无用数据
            deq.removeFirst();
        }
        while(!deq.isEmpty() && nums[i] > nums[deq.getLast()]){ 
          //如果当前值大于之前所有的值 则删除 
            deq.removeLast();
        }
    }
    
  • 相关阅读:
    SQL Data Services Abandons REST for TDS API and Knocks My Socks Off
    C# Lambda Expressions 简介
    Web.config 和 App.config 区别
    XPO 第三方控件学习(DevExpress Persistent Object )系列查询
    进销存管理系统 系列
    MOSS 学习系列(十万个为什么)--为什么我要定制审批流程的时候找不到审批的选项?
    XPO 第三方控件学习(DevExpress Persistent Object )系列 其他(session,事务,有效性检查...
    如何使用三态工作流(一)
    english interview example
    How to build a K2 SharePoint Workflow(2)
  • 原文地址:https://www.cnblogs.com/qxlxi/p/12860660.html
Copyright © 2020-2023  润新知