滑动窗口

本文深入探讨了滑动窗口算法,详细介绍了其概念、代码模板及常见易错点,并通过值匹配和区间匹配两个例题解析,帮助读者掌握这一算法,提升解题速度和准确性。重点讲解了在滑动窗口中如何处理左右指针滑动的条件和变量变化。
摘要由CSDN通过智能技术生成

一、前言

  1. 在数组中查找一个数,可以使用二分法查找,但是算法问题中还有一些是在数组中查找一个区间,这时滑动窗口就是一种很好的解决思路。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RyRWM6ol-1616989693356)(image-20210314202139804.png)]

  2. 很多同学学过滑动窗口算法,但是一做题就错,这是因为有很多细节问题会在解答时出错,本文将依次介绍该算法的模板,易错点,分类题型,希望读者看完之后能极大的提高做题速度以及准确度。

二、什么是滑动窗口

  1. 概念:滑动窗口是双指针算法的一种,利用双指针在数组单一方向滑动,形成一个子区间,对子区间进行剪枝,最终得出满足条件的解。

  2. 过程如下:

    windows中元素未完全包含target时,right向右滑动

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q7zymImC-1616989693359)(image-20210314215812195.png)]

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pB7KchBo-1616989693361)(image-20210314215831073.png)]

    此时window包含target中所有元素,将left向右滑动

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-60vB6MmT-1616989693362)(image-20210314215844471.png)]

  3. 代码模板

    func checkInclusion(nums []int, target []int) bool {
      windows := make(map[byte]int, len(nums))
    	left, right := 0, 0
      
    	for right < len(nums) {
    		c := nums[right]
    		windows[c]++
    		//right右滑变量变化
    		right++
        
    		for 满足left右滑条件 {
    			//判断区间是否满足条件(可能在left右滑的前中后)
          
    			d := nums[left]
    			//left右滑变量的改动
          
    			left++
    		}
    	}
    	return false
    }
    

    易错点:

    • left和right滑动时,容易漏掉某个变量的值变化,这里教大家一个技巧,每次写完复查前面声明的变量,在滑动时是否改变
    • left右滑动时,先判断是否满足条件,再做变量值的变化,颠倒会导致第一次满足条件的解漏掉

三、例题解析

3.1 值匹配

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FopPFQrd-1616989693364)(image-20210314223902595.png)]

分析:这道题是求最长子串,这里我们需要敏感地捕捉到“子串”关键词。该题中,我们把字符串当做数组,子区间就是“子串”,这赤裸裸的就是滑动窗口的题型呀。废话不多说,直接先上模板!

func lengthOfLongestSubstring(s string) int {
	lens := len(s)
	window := make(map[byte]int, lens)
  left, right := 0, 0
  
	for right < lens{
		c := nums[right]
		windows[c]++
		//right右滑变量变化
		right++
    
		for 满足left右滑条件 {
			//判断区间是否满足条件(可能在left右滑的前中后)
      
			d := nums[left]
			//left右滑变量的改动
      
			left++
		}
	}
	return false
}
  1. 满足left右滑动的条件:无重复字符,即右滑时window容器中每个元素值<=1
  2. 是否更新结果值条件:在window中无重复的元素后,即for循环之后,判断res-left与之前无重复字符串最大长度(res)之间关系
  3. right右滑动变量变化:参照声明的四个变量,这题只有winows和right变化
  4. left右滑动变量变化:参照声明的四个变量,这题只有winows和left变化
func lengthOfLongestSubstring(s string) int {
	lens := len(s)
	window := make(map[byte]int, lens)
	left, right, res := 0, 0, 0
  
  //right右滑动
	for right < lens {
		b := s[right]
		window[b]++
		right++
    //left右滑动
		for window[b] > 1 {
			c := s[left]
			window[c]--
			left++
		}
    //判断区间是否满足条件
		if right-left > res {
			res = right - left
		}
	}
	return res
}
3.2 区间匹配

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7OSAA9E-1616989693365)(image-20210314223919662.png)]

分析:

  1. 满足left右滑动的条件:这题和前言中题类似,设一个target切片记录目标区间每个元素的个数[A:1,B:1,C:1],当windows中所有目标元素个数(vaild)都达到target要求时,left右滑缩小区间
  2. 是否更新结果值条件:在left右滑时,即for循环中判断当前right-left与之前最小覆盖子串之间关系
  3. right右滑动变量变化:参照声明的变量有当前区间window,达标元素个数vaild,right
  4. left右滑动变量变化:参照声明的变量有起始位置start,结果字符串长度res,达标元素个数vaild,当前区间window,left
func minWindow(s string, t string) string {
  //变量初始化
	lens := len(s)
	lent := len(t)
	window := make(map[byte]int, lens)
	target := make(map[byte]int, lent)
	left, right, vaild := 0, 0, 0
	res := lens
	start := -1

	for i := 0; i < lent; i++ {
		target[t[i]]++
	}

  //right右滑动
	for right < lens {
		b := s[right]
		window[b]++
		if target[b] == window[b] {
			vaild++
		}
		right++
    
    //left右滑动
		for vaild == len(target) {
			c := s[left]
      //是否更新结果值
			if res >= right-left {
				start = left
				res = right - left
			}
            
			if window[c] == target[c] {
				vaild--
			}
      window[c]--
			left++
		}
	}
	if start == -1 {
		return ""
	}
	return s[start : start+res]
}

五、总结

  1. 出题点:一种是不需要申请额外的容器去做判断,一种需要申请额外的区间(target)去做判断
  2. 记住模板:一容(window),二变(left,right),三扩(right右移),四缩(left右移)
  3. 思路:俩个条件(left右滑条件,是否更新结果值条件),俩个变化(right右滑动变量变化,left右滑动变量变化)
  4. 易错点:例如第二题每次滑动需要更新的变量很多,稍有不慎就会少更新某个变量,每次对照开始声明的变量可以万无一失
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值