滑动窗口

Posted 请务必优秀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了滑动窗口相关的知识,希望对你有一定的参考价值。

滑动窗口是一种想象出来的数据结构:

  1. 左边界l和右边界r
  2. l往右滑意味着一个样本出了窗口,r往右滑意味着一个样本进了窗口,l和r都只能往右滑

滑动内最大值和最小值的更新结构

窗口不管l还是r滑动之后,都会让窗口呈现新状况,如何能够更快的得到窗口当前状况下的最大值和最小值?最好平均下来复杂度能做到O(1)

利用单调双端队列

窗口本质:哪些数会依次成为最大数的优先级

剑指 Offer 59 - I. 滑动窗口的最大值

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

输入: 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
class Solution 
    public int[] maxSlidingWindow(int[] nums, int k) 
    	if(nums == null || k < 1 || nums.length < k) 
    		return new int[0];
    	
    	
    	LinkedList<Integer> qmax = new LinkedList<Integer>();
    	int[] res = 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) 
    			res[index++] = nums[qmax.peekFirst()];
    		
		
    	return res;
    

求达标子数组的数量

给定一个整型数组arr,和一个整数num

某个arr中的子数组sub,如果想达标,必须满足:

sub中最大值 – sub中最小值 <= num

返回arr中达标子数组的数量

	public static int subArrayNum(int[] arr, int num) 
		
    	if(arr == null || num < 0 || arr.length == 0) 
    		return 0;
    	
    	
    	LinkedList<Integer> qmin = new LinkedList<Integer>();
    	LinkedList<Integer> qmax = new LinkedList<Integer>();
    	
    	int l = 0;
    	int r = 0;
    	//[l...r) -> [0,0) 窗口内无数
    	
    	int res = 0;
    	
    	while(l < arr.length) 
    		while(r < arr.length) 
    			while(!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[r]) 
    				qmin.pollLast();
    			
    			qmin.addLast(r);
    			
    			while(!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[r]) 
    				qmax.pollLast();
    			
    			qmax.addLast(r);
    			
    			if(arr[qmax.getFirst()] - arr[qmin.getFirst()] > num) 
    				break;
    			
    			r++;
    		
    		
    		res += r -l;
    		if(qmin.peekFirst() == l) 
    			qmin.pollFirst();
    		
    		if(qmax.peekFirst() == l) 
    			qmax.pollFirst();
    		
    		
    		l++;
    	
    	
    	return res;
	

对于此题:

  1. 当前范围内若达标,则缩小范围必达标
  2. 若不达标,则扩大范围必不达标,可以及时break

遇到题,先看看问题本身和范围是否能够建立单调性,然后选择对应流程及流程中所要的信息

每个人都有潜在的能量,只是很容易被习惯所掩盖,被时间所迷离,被惰性所消磨~

以上是关于滑动窗口的主要内容,如果未能解决你的问题,请参考以下文章

我的片段中有 webview,当滑动 webview 时, viewPager 也开始滑动

我的应用程序使用片段,但我需要从左到右从右向左滑动

在一个片段中检测Recyclerview的上下滑动,我怎么做?

选项卡执行android中下一个片段中存在的代码

华为OD机试 -滑动窗口最大和(Java) | 机试题+算法思路+考点+代码解析 2023

华为OD机试 -滑动窗口最大和(Java) | 机试题+算法思路+考点+代码解析 2023