【滑动窗口最大值】Java优先队列——Queue接口-PriorityQueue类
题目描述:
1e5大小的nums[]数组中长度为k(1<=k<=1e5)的窗口的最大值
题解:
暴力求解O(n^2)会超时,需要O(nlogn)的解法
使用大根堆优先队列维护窗口元素,每次取最大值复杂度降为O(1),堆结构维护复杂度O(logn)
问:如果维护窗口[l, r]前[0, l - 1]的元素不影响题目结果?
答:维护队头元素的下标在窗口[l, r]内即可。换句话说,在每次取队头元素之前,先判断队头元素是否在当前合法的窗口内,如果不合法就使其出队,如果合法那么队头元素就是当前窗口的最大值,因为窗口的移动间距为1,因此每次最多出队一个元素,因此查询最大值的复杂度最高为O(logn)
使用自定义内部类Pair维护(id, nums[id])
class Solution { class Pair{ int id = 0; int val = 0; Pair(int id, int val) { this.id = id; this.val = val; } } public int[] maxSlidingWindow(int[] nums, int k) { Queue<Pair> pq = new PriorityQueue<>((o1, o2) -> { if(o1.val != o2.val) return o2.val - o1.val; return o1.id - o2.id; }); int len = nums.length; int[] ans = new int[len - k + 1]; for(int i = 0; i < k; ++ i ){ pq.offer(new Pair(i, nums[i])); } ans[0] = pq.peek().val; int st = 0; for(int i = k; i < len; ++ i ) { pq.offer(new Pair(i, nums[i])); while(pq.peek().id < i - k + 1) pq.poll(); ans[++ st] = pq.peek().val; } return ans; } }
使用int[]维护(id, nums[id])
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { Queue<int[]> pq = new PriorityQueue<>((o1, o2) -> { if(o1[1] != o2[1]) return o2[1] - o1[1]; return o1[0] - o2[0]; }); int len = nums.length; int[] ans = new int[len - k + 1]; for(int i = 0; i < k; ++ i ) { pq.offer(new int[]{i, nums[i]}); } ans[0] = pq.peek()[1]; int st = 0; for(int i = k; i < len; ++ i ) { pq.offer(new int[]{i, nums[i]}); while(pq.peek()[0] < i - k + 1) pq.poll(); ans[++ st] = pq.peek()[1]; } return ans; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效