LeetCode hot100-11

java 复制代码
239. 滑动窗口最大值

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

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

我的解法会超时,就比最暴力解法优化了一点点吧。能通过49/51。

思路就是左右指针中间的是窗口。记录当前窗口的最大值,窗口滑动一下,原来左指针的值出去了,新的右指针的值进来了。其实就变了两个数。就比较下新进来这个数比最大值大还是小,大的话就成为新的最大值。出去这个数比较麻烦,如果出去的是最大值的话,就要重新比较当前整个窗口找到新的最大值。就是这一步引入了第二重循环,导致会超时。

贴一下我的代码

java 复制代码
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 0) {
            return new int[0];
        }
        int[] res = new int[nums.length - k + 1];
        int max = nums[0];
        for (int i = 0; i < k; i++) {
            if (nums[i] > max) {
                max = nums[i];
            }
        }
        res[0] = max;
        for (int i = 1; i < nums.length - k + 1; i++) {
            int j = k + i - 1;
            if (nums[j] > max) {
                max = nums[j];
            } else if (max == nums[i - 1]) {
                max = nums[i];
                for (int g = i; g <= j; g++) {
                    max = Math.max(nums[g], max);
                }
            }
            res[i] = max;

        }
        return res;

    }
}

我只看了官方解法一,困难档次的题我就不追求优化了。

解法一其实和我的想法一样,但是为了不超时,那个两重循环必须去掉。第二重循环其实就是为了找比大小。堆排序是可以降低时间复杂度的,所以就用了Java里的优先队列,用了比较器之后可以看做一个大顶堆。这个堆的每个节点是int[2]的类型,int[0]是节点的值,int[1]是节点在数组中的下标。这个下标记录下来就是为了实现如果左指针指的是滑动窗口的最大值,滑一下,就找不到最大值的这种情况。当发生这种情况时,就把堆顶移出去(也就是左指针指的那个)。移出去之后会自动构建新的大顶堆,直接就找到新的最大值了。注意这种解法堆里面的元素并不一直是k个,它里面有多少元素根本不关心,只关心当前的最大值,和最大值是否还在滑动窗口里面。所以它在移除滑动窗口之外的数据时用的while循环,因为可能第一大的节点和第二大的节点都还在堆里,但是已经在滑动窗口之外了。

大顶堆是这样定义的,Java的比较器我也不太会。记一下对于优先队列O1-O2是默认的,从小到大,O2-O1是从大到小。这里用的int[]的数据类型,用的pair2-pair1,就是从大到小。先按元素值从大到小,pair2[0] - pair1[0]。如果元素值相等,再按元素下标从大到小pair2[1] - pair1[1]

PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() {

public int compare(int[] pair1, int[] pair2) {

return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];

}

});

再记一下PriorityQueue的几个方法,添加元素offer, 获取堆顶元素peek, 弹出堆顶元素poll.

javaclass 复制代码
    public int[] maxSlidingWindow(int[] nums, int k) {
        int n = nums.length;
        PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] pair1, int[] pair2) {
                return pair1[0] != pair2[0] ? pair2[0] - pair1[0] : pair2[1] - pair1[1];
            }
        });
        for (int i = 0; i < k; ++i) {
            pq.offer(new int[]{nums[i], i});
        }
        int[] ans = new int[n - k + 1];
        ans[0] = pq.peek()[0];
        for (int i = k; i < n; ++i) {
            pq.offer(new int[]{nums[i], i});
            while (pq.peek()[1] <= i - k) {
                pq.poll();
            }
            ans[i - k + 1] = pq.peek()[0];
        }
        return ans;
    }
}

作者:力扣官方题解
链接:https://leetcode.cn/problems/sliding-window-maximum/solutions/543426/hua-dong-chuang-kou-zui-da-zhi-by-leetco-ki6m/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关推荐
艾莉丝努力练剑7 小时前
【Linux:文件】Ext系列文件系统(初阶)
大数据·linux·运维·服务器·c++·人工智能·算法
偷吃的耗子8 小时前
【CNN算法理解】:CNN平移不变性详解:数学原理与实例
人工智能·算法·cnn
dazzle9 小时前
机器学习算法原理与实践-入门(三):使用数学方法实现KNN
人工智能·算法·机器学习
那个村的李富贵9 小时前
智能炼金术:CANN加速的新材料AI设计系统
人工智能·算法·aigc·cann
张张努力变强9 小时前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl
万岳科技系统开发9 小时前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
张登杰踩9 小时前
MCR ALS 多元曲线分辨算法详解
算法
YuTaoShao9 小时前
【LeetCode 每日一题】3634. 使数组平衡的最少移除数目——(解法一)排序+滑动窗口
算法·leetcode·排序算法
波波0079 小时前
每日一题:.NET 的 GC是如何分代工作的?
算法·.net·gc
HY小宝F9 小时前
职场沟通的深层智慧:从对抗到协作的自我修炼
职场和发展