leetcode239-滑动窗口最大值

原题

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

返回滑动窗口中的最大值。

进阶:

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

示例 1:

输入: 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 <= nums.length <= 10^5
  • -10^4 <= nums[i] <= 10^4
  • 1 <= k <= nums.length
     

解法

思想

使用一个双端队列维护一个单调递减队列(但实际上存放的是数组的下标),每滑动一次窗口,如果进来的元素比队尾下标对应的元素小,则进入队尾,否则将队列尾比该元素小的元素都弹出(类似单调栈的思想),再进入队尾,那么任意时刻队首元素即为当前最大元素的下标,而如果滑动窗口后队首元素的下标等于当前下标-k,说明队首元素过期,应该从队列首部弹出。

代码

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> qmax = new LinkedList<>();
        int[] ans = new int[nums.length-k+1];
        int index = 0;
        for(int i = 0;i<nums.length;i++){
            while(!qmax.isEmpty()&&nums[qmax.peekLast()]<=nums[i]){
                qmax.pollLast();
            }
            qmax.addLast(i);
            if(qmax.peekFirst()==i-k){
                qmax.pollFirst();
            }
            if(i>=k-1){
                ans[index++] = nums[qmax.peekFirst()];
            }
        }
        return ans;
    }
}

下面这种方法的思想是记录当前窗口内最大元素的下标,如果滑出去了重新选举最大值,如果没滑出去将进来的元素与当前最大元素比较。它和暴力又不太一样,因为其实重新选举的次数较少,实际leetcode中这种方法反而更快,可能是因为数据量的原因:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length == 0 || k < 1)return new int[0];
        if(k == 1)return nums;
        int[] maxes = new int[nums.length - k + 1];
        int maxIdx = 0;
        //求出前k个元素的最大值索引
        for(int i = 1; i < k; i++){
            if(nums[i] > nums[maxIdx])maxIdx = i;
        }
        //li是滑动窗口的最左端
        for(int li = 0; li < maxes.length; li++){
            //ri是滑动窗口的最右端的索引
            int ri = li + k- 1;
            if(maxIdx < li){//最大值的索引不在滑动窗口范围内
                maxIdx = li;
                //求出[li, ri]范围内最大值的索引
                for(int i = li + 1; i <= ri; i++){
                    if(nums[i] > nums[maxIdx])maxIdx = i;
                }
            }else if(nums[ri] >= nums[maxIdx]){//最大值的索引在滑动窗口的范围内,并且大于最大值
                maxIdx = ri;
            }
            maxes[li] = nums[maxIdx];
        }
        return maxes;
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode239-%e6%bb%91%e5%8a%a8%e7%aa%97%e5%8f%a3%e6%9c%80%e5%a4%a7%e5%80%bc/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年4月21日
下一篇 2020年4月22日

相关推荐

  • 十大排序算法与Java实现

    本文参考资源: https://github.com/iTimeTraveler/SortAlgorithms 十大经典排序算法 - 冰狼爱魔 - 博客园 十大经典排序算法总结(J…

    2020年3月11日
    0800
  • leetcode9-回文数

    原题 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 示例1: 输入: 121 输出: true 示例2: 输入: -121 输出: fa…

    算法 2020年2月28日
    0120
  • 程序员面试金典01.06-字符串压缩

    原题(来源Leetcode) 字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字…

    算法 2020年3月16日
    0230
  • leetcode705-设计哈希集合

    原题 不使用任何内建的哈希表库设计一个哈希集合 具体地说,你的设计应该包含以下的功能 add(value):向哈希集合中插入一个值。 contains(value) :返回哈希集合…

    算法 2019年12月18日
    0140
  • leetcode14-最长公共前缀

    原题 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 “”。 示例 1: 输入: [“flower”,”flow”,”flight”] 输出: “…

    算法 2019年11月18日
    0100
  • leetcode225--用队列实现栈

    原题 使用队列实现栈的下列操作: push(x) – 元素 x 入栈 pop() – 移除栈顶元素 top() – 获取栈顶元素 empty() – 返回栈是否为空 注意: 你只能…

    算法 2019年12月13日
    0120
  • leetcode124-二叉树中的最大路径和

    原题 给定一个非空二叉树,返回其最大路径和。 本题中,路径被定义为一条从树中任意节点出发,达到任意节点的序列。该路径至少包含一个节点,且不一定经过根节点。 示例 1: 输入: [1…

    算法 2020年4月26日
    0170
  • leetcode1095-山脉数组中查找目标值

    原题 (这是一个 交互式问题 ) 给你一个 山脉数组 mountainArr,请你返回能够使得 mountainArr.get(index) 等于 target 最小 的下标 in…

    算法 2020年4月29日
    0150
  • leetcode122-买卖股票的最佳时机II

    原题 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。 注意: 你不能同…

    算法 2020年2月7日
    080
  • leetcode990-等式方程的可满足性

    原题 给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a…

    算法 2020年6月8日
    0100

发表回复

登录后才能评论