题目链接:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
算法思想:
法一(暴力):
暴力的算法是我刚开始做这个题目使用的方法,通过了测试用例,但是提交的时候超出了时间限制,我就说暴力能通过的话为什么设定成困难,但是这也一种思想,不详细介绍了,代码如下:
public int[] maxSlidingWindow(int[] nums, int k) {//定义一个数组用来存储窗口中的最大值int[] ret = new int[nums.length-k+1];for(int i = 0;i < nums.length - k + 1;i++) {int max = getMax(nums,i,i+k-1);ret[i] = max;}return ret;}public int getMax(int[] nums,int l,int r) {int max = Integer.MIN_VALUE;for(int i = l;i <= r;i++) {if(nums[i] > max) {max = nums[i];}}return max;}
法二(单调队列):
这个题目的核心目的就是维护一个滑动窗口,滑动窗口在滑动的时候,最左边的元素出窗口,出窗口的同时会有一个元素入窗口,每进行一次这个操作的时候就需要判断一下窗口内所有元素的最大值,并将最大值加入到一个数组中,滑动结束后返回数组;那么有没有一种数据结构可以在最左边弹出元素,最右边插入元素,而且内部的元素具有单调性,就很容易想到Java中的双端队列了,我们只需要在维护双端队列中的单调性即可,使得最大的元素永远在队列的最左边,这样每次加入到数组中的最大值永远是队列最左边的元素了
public int[] maxSlidingWindow(int[] nums, int k) {int n = nums.length;int[] ans = new int[n - k + 1];Deque<Integer> q = new ArrayDeque<>(); // 双端队列for (int i = 0; i < n; i++) {// 1. 入队列while (!q.isEmpty() && nums[q.getLast()] <= nums[i]) {q.removeLast(); // 维护 q 的单调性(假设插入的元素比队列的最右边的元素大时,弹出最右边的元素)}q.addLast(i); // 入队// 2. 出if (i - q.getFirst() >= k) { // 队首已经离开窗口了q.removeFirst();}// 3. 记录答案if (i >= k - 1) {// 由于队首到队尾单调递减,所以窗口最大值就是队首ans[i - k + 1] = nums[q.getFirst()];}}return ans;}