惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Martin Fowler
Martin Fowler
I
InfoQ
腾讯CDC
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
爱范儿
爱范儿
Microsoft Security Blog
Microsoft Security Blog
Google DeepMind News
Google DeepMind News
D
DataBreaches.Net
云风的 BLOG
云风的 BLOG
F
Fortinet All Blogs
N
Netflix TechBlog - Medium
博客园 - 聂微东
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
博客园 - 三生石上(FineUI控件)
Y
Y Combinator Blog
博客园 - Franky
Engineering at Meta
Engineering at Meta
B
Blog
罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
Jina AI
Jina AI
V
Visual Studio Blog

蛮荆

如何获取更多的免费服务器 Kubernetes 调度器队列 - 设计与实现 Kubernetes 调度器 - 核心流程 Kubernetes Networking Model & CNI Kubernetes 控制器管理总结 Kubernetes CronJob 设计与实现 Kubernetes Job 设计与实现 Kubernetes HPA 设计与实现 Kubernetes Deployment 滚动更新实现原理 Kubernetes GC 设计与实现 Kubernetes Pod 驱逐 - 设计与实现 Kubernetes Daemonset 设计与实现 Kubernetes ReplicaSet 设计与实现 Kubernetes EndPoint 设计与实现 Kubernetes Informer 设计与实现 降本增效之应用优化 (三) 日志存储与检索 Kubernetes Pod 设计与实现 - 创建流程 Kubernetes 探针设计与实现 Unix 编程艺术名句摘录 Kubernetes - CRI 概述 Golang 编译速度为什么这么快? Kubernetes Pod 设计与实现 - Pause 容器 Kubernetes - kube-proxy 代理模式工程优化 Kubernetes 应用最佳实践 - 优雅关闭长连接 Kubernetes Service 类型和会话亲和性 Kubernetes 为什么需要 Ingress Kubernetes 架构 - 控制平面和数据平面 降本增效之应用优化 (二) 大报表 Go 语言如何获取 CPU 利用率 降本增效之应用优化 (一) Redis
LeetCode Sliding Window 刷题模板
2022-04-10 · via 蛮荆

2022-04-10 算法 LeetCode

📖 概述

滑动窗口(Sliding Window)是一种用于解决数组/字符串相关问题的常见技巧,通过维护一个大小可以伸缩的窗口来执行具体操作,随着窗口在数组/字符串上移动,根据窗口的变化来执行具体的操作。

刷题模板

滑动窗口算法执行的基本步骤:

  1. 初始化左指针 left 和右指针 right,并且初始化结果变量
  2. 移动右指针,扩大窗口大小,直到满足特定条件 (窗口内的元素满足某种条件 或 达到数组/字符串的末尾)
  3. 移动左指针,缩小窗口大小 (直到不再满足特定条件) 同时更新结果变量
  4. 重复步骤 2 和 3,直到右指针达到数组/字符串的末尾

下面是一个典型的滑动窗口执行过程示例:

滑动窗口执行过程示例

// 滑动窗口刷题代码模板
func slidingWindow(nums []int) int {
	// 初始化左右指针
	left, right := 0, 0
	// 初始化结果变量
	result := 0

	// 迭代右指针
	for right < len(nums) {
		// 更新窗口状态

		// 移动左指针,收缩窗口大小,更新结果变量

		// 更新右指针,扩大窗口大小
	}

	return result
}

💡 典型题目

1. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

# 示例来源: https://leetcode.cn/

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

解题思路:

  1. 初始化左指针 left 和右指针 right,并且初始化结果最小长度
  2. 移动右指针,扩大窗口大小,直到满足特定条件 (窗口内的元素和大于等于目标参数 或 达到数组的末尾)
  3. 移动左指针,缩小窗口大小 (窗口内的元素和小于目标参数) 同时更新结果变量
  4. 重复步骤 2 和 3,直到右指针达到数组的末尾
// 题解代码
func minSubArrayLen(target int, nums []int) int {
	// 初始化最小长度为数组长度 + 1
	minLen := len(nums) + 1
	sum, left := 0, 0

	// 移动右指针
	for right := range nums {
		sum += nums[right]

		// 找到符合条件的子数组时,开始收缩窗口大小
		for sum >= target {
			minLen = min(minLen, right-left+1)
			sum -= nums[left]
			left++
		}
	}

	// 如果最小长度依然等于数组长度 + 1
	// 说明数组中不存在符合条件的子数组
	if minLen > len(nums) {
		return 0
	}
	return minLen
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

长度最小的子数组 - 代码执行过程

2. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

# 示例来源: https://leetcode.cn/

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

解题思路:

  1. 初始化左指针 left 和右指针 right,并且初始化结果最小长度,同时维护一个 Map 作为窗口内的重复字符检测
  2. 移动右指针,扩大窗口大小,直到满足特定条件 (窗口内的元素出现重复 或 达到字符串的末尾)
  3. 移动左指针,缩小窗口大小 (窗口内的元素没有重复) 同时更新结果变量.
  4. 重复步骤 2 和 3,直到右指针达到字符串的末尾
// 题解代码
func lengthOfLongestSubstring(s string) int {
	// 题目声明字符串 s 由英文字母、数字、符号和空格组成
	// 所以这里使用一个长度为 256 的数组来模拟 Map 功能
	var win [256]int
	res, n := 0, len(s)

	// 声明左右指针
	for left, right := 0, 0; right < n; right++ {
		c := s[right]
		// 更新窗口
		win[c]++

		// 遇到重复的字符时,开始收缩窗口大小
		for win[c] > 1 {
			win[s[left]]--
			left++
		}

		// 更新已知的最大窗口
		res = max(res, right-left+1)
	}

	return res
}

无重复字符的最长子串 - 代码执行过程