算法-滑动窗口

滑动窗口的特征

窗口由两个指针(通常称为左指针和右指针)定义,维护一个动态大小的窗口

滑动窗口的简单图解

简单的例子:有A - H的连续按字母表升序的字符串,需要找到同时包含DEF的最小子字符串。

以下图解流程为滑动窗口的初始定义以及滑动的一个过程。(初始化、扩大边界、缩小边界)

1、维护2个指针start和end,同时指向A。start和end为窗口的边界。

2、开始向右移动end到B,得到窗口AB。发现窗口没有包含DEF,持续移动end,扩大右边界。

3、继续向右移动end,扩大右边界,一直移动到F,得到窗口A- F,同时包含DEF。

4、向右移动start,缩小左边界,得到同时包含DEF的最小窗口D-F

滑动窗口的应用场景

1、寻找字符串中的最小覆盖子串

2、计算数组中满足特定条件的子数组数量

3、最长无重复子串

4、时间滑动窗口:限流、计数统计等

题型思考

题目:无重复字符的最长子串

举例分析字符串:ababcaac

1、初始存储一个map,记录字符是否出现过

2、移动right,一直移动到c,发现下一个a在map{a,b,c}中出现过,停止right的移动,记录此时的子串长度。

3、移动left,并从map中删除掉a,此时map为{b,c}

4、重复以上2轮步骤,移动right找到右边界,然后再移动left,缩小边界,再移动right,扩大右边界,循环一直到结束,记录最大的子串长度。

代码如下:

func lengthOfLongestSubstring(s string) int {
	// 记录每个字符是否出现过
	recordMap := map[byte]int{}
	n := len(s)
	// 右指针,初始值为 -1,相当于字符串的左边界的左侧
	rightIndex, result := -1, 0
	for i := 0; i < n; i++ {
		if i != 0 {
			// 左指针向右移动一格,移除掉之前的字符
			delete(recordMap, s[i-1])
		}
		for rightIndex+1 < n && recordMap[s[rightIndex+1]] == 0 {
			// 不断地移动右指针
			recordMap[s[rightIndex+1]]++
			rightIndex++
		}
		// 无重复字符子串长度: 第 i 到 rightIndex 个字符
		result = max(result, rightIndex-i+1)
	}
	return result
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值