我们可以利用双端队列来实现一个窗口,目的是让该窗口可以做到张弛有度(汉语博大精深,也就是长度动态变化。其实用游标或者其他解法的目的都是一样的,就是去维护一个可变长的窗口)
然后我们再做一件事,只要遍历该数组,同时在双端队列的头去维护当前窗口的最大值(在遍历过程中,发现当前元素比队列中的元素大,就将原来队列中的元素祭天),在整个遍历的过程中我们再记录下每一个窗口的最大值到结果数组中。最终结果数组就是我们想要的,整体图解如下。
假设 nums = [1,3,-1,-3,5,3,6,7],和 k = 3
(个人认为我画的这个图是目前全网对于双端队列本题解法比较清晰的一个...所以我觉得如果不点个赞的话...晤..)
根据分析,得出代码:
//go func maxSlidingWindow(nums []int, k int) []int { if len(nums) == 0 { return []int{} } //用切片模拟一个双端队列 queue := []int{} result := []int{} for i := range nums { for i > 0 && (len(queue) > 0) && nums[i] > queue[len(queue)-1] { //将比当前元素小的元素祭天 queue = queue[:len(queue)-1] } //将当前元素放入queue中 queue = append(queue, nums[i]) if i >= k && nums[i-k] == queue[0] { //维护队列,保证其头元素为当前窗口最大值 queue = queue[1:] } if i >= k-1 { //放入结果数组 result = append(result, queue[0]) } } return result }Perfact~题目完成!看着一下子超越百分之99的用户,是不是感觉很爽呢~ //Java class Solution { public int[] maxSlidingWindow(int[] nums, int k) { if(nums == null || nums.length < 2) return nums; // 双向队列 保存当前窗口最大值的数组位置 保证队列中数组位置的数值按从大到小排序 LinkedList<Integer> queue = new LinkedList(); // 结果数组 int[] result = new int[nums.length-k+1]; // 遍历nums数组 for(int i = 0;i < nums.length;i++){ // 保证从大到小 如果前面数小则需要依次弹出,直至满足要求 while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]){ queue.pollLast(); } // 添加当前值对应的数组下标 queue.addLast(i); // 判断当前队列中队首的值是否有效 if(queue.peek() <= i-k){ queue.poll(); } // 当窗口长度为k时 保存当前窗口中最大值 if(i+1 >= k){ result[i+1-k] = nums[queue.peek()]; } } return result; } }