当前位置: 首页 > news >正文

不定长滑动窗口(求最短/最小)

选自灵神题单,不定长滑动窗口 2.2 。

209. 长度最小的子数组

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

找出该数组中满足其总和大于等于 target 的长度最小的

[numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度**。**如果不存在符合条件的子数组,返回 0

示例 1:

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

示例 2:

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

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:left = 0ans = infsum_ = 0for right, x in enumerate(nums):sum_ += xwhile sum_ - nums[left] >= target:sum_ -= nums[left]left += 1if sum_ >= target:  # 一定要加这个条件,避免刚开始时上面的while循环不会进入,而总和不满足条件却记录了结果ans = min(ans, right - left + 1)return ans if ans != inf else 0


2904. 最短且字典序最小的美丽子字符串

给你一个二进制字符串 s 和一个正整数 k

如果 s 的某个子字符串中 1 的个数恰好等于 k ,则称这个子字符串是一个 美丽子字符串

len 等于 最短 美丽子字符串的长度。

返回长度等于 len 且字典序 最小 的美丽子字符串。如果 s 中不含美丽子字符串,则返回一个 字符串。

对于相同长度的两个字符串 ab ,如果在 ab 出现不同的第一个位置上,a 中该位置上的字符严格大于 b 中的对应字符,则认为字符串 a 字典序 大于 字符串 b

  • 例如,"abcd" 的字典序大于 "abcc" ,因为两个字符串出现不同的第一个位置对应第四个字符,而 d 大于 c

示例 1:

输入:s = "100011001", k = 3
输出:"11001"
解释:示例中共有 7 个美丽子字符串:
1. 子字符串 "100011001" 。
2. 子字符串 "100011001" 。
3. 子字符串 "100011001" 。
4. 子字符串 "100011001" 。
5. 子字符串 "100011001" 。
6. 子字符串 "100011001" 。
7. 子字符串 "100011001" 。
最短美丽子字符串的长度是 5 。
长度为 5 且字典序最小的美丽子字符串是子字符串 "11001" 。

示例 2:

输入:s = "1011", k = 2
输出:"11"
解释:示例中共有 3 个美丽子字符串:
1. 子字符串 "1011" 。
2. 子字符串 "1011" 。
3. 子字符串 "1011" 。
最短美丽子字符串的长度是 2 。
长度为 2 且字典序最小的美丽子字符串是子字符串 "11" 。 

示例 3:

输入:s = "000", k = 1
输出:""
解释:示例中不存在美丽子字符串。

class Solution:def shortestBeautifulSubstring(self, s: str, k: int) -> str:if s.count("1") < k:return ""left = 0ans = ""count = inf  # 结果字符串的长度for right, x in enumerate(s):if x == "1":k -= 1# 如果窗口内的1的个数超过k,或者窗口端点是0,就可以缩小窗口# 直到左端点是窗口内1的个数恰好是k的边界为止while k < 0 or s[left] == "0":if s[left] == "1":k += 1left += 1if (k == 0  # 加这个条件是为了刚开始避免k一次也没减,直接记录结果and right - left + 1 < countor right - left + 1 == countand ans> s[left : right + 1]  # 如果结果字符串和滑动窗口长度一样,选择字典序小的):ans = s[left : right + 1]count = right - left + 1  # 更新结果字符串的长度return ans


1234. 替换子串得到平衡字符串

有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。

假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。

你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0

示例 1:

输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。

示例 2:

输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例 3:

输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。 

示例 4:

输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。

class Solution:# 思路:找到元素个数大于目标值的那部分,找到包含这些部分的最小子串,将这个子串中的某个字符替换成元素个数较少的字符# 不过我们并不在意替换的细节,所以只需要找到这个最小子串的长度就好了def balancedString(self, s: str) -> int:# 统计窗口内字符元素个数与目标值的差值win = {"Q": s.count("Q") - len(s) // 4,"W": s.count("W") - len(s) // 4,"E": s.count("E") - len(s) // 4,"R": s.count("R") - len(s) // 4,}# 如果元素个数与目标值差值都为0,则该字符串符合条件,直接返回0if min(win.values()) == 0:return 0# 收集需要删除的键,保留元素个数多出来的部分keys_to_delete = [i for i in win if win[i] <= 0]# 删除这些键for key in keys_to_delete:del win[key]left = 0ans = inffor right, x in enumerate(s):if x in win:win[x] -= 1# 当窗口内字符满足条件时,就可以缩小窗口了,同时也是收割结果的时候while all([i <= 0 for i in win.values()]):ans = min(ans, right - left + 1)if s[left] in win:win[s[left]] += 1left += 1return ans


2875. 无限数组的最短子数组

给你一个下标从 0 开始的数组 nums 和一个整数 target

下标从 0 开始的数组 infinite_nums 是通过无限地将 nums 的元素追加到自己之后生成的。

请你从 infinite_nums 中找出满足 元素和 等于 target最短 子数组,并返回该子数组的长度。如果不存在满足条件的子数组,返回 -1

示例 1:

输入:nums = [1,2,3], target = 5
输出:2
解释:在这个例子中 infinite_nums = [1,2,3,1,2,3,1,2,...] 。
区间 [1,2] 内的子数组的元素和等于 target = 5 ,且长度 length = 2 。
可以证明,当元素和等于目标值 target = 5 时,2 是子数组的最短长度。

示例 2:

输入:nums = [1,1,1,2,3], target = 4
输出:2
解释:在这个例子中 infinite_nums = [1,1,1,2,3,1,1,1,2,3,1,1,...].
区间 [4,5] 内的子数组的元素和等于 target = 4 ,且长度 length = 2 。
可以证明,当元素和等于目标值 target = 4 时,2 是子数组的最短长度。

示例 3:

输入:nums = [2,4,6,8], target = 3
输出:-1
解释:在这个例子中 infinite_nums = [2,4,6,8,2,4,6,8,...] 。
可以证明,不存在元素和等于目标值 target = 3 的子数组。

class Solution:def minSizeSubarray(self, nums: List[int], target: int) -> int:# # 将target值分为两部分,一部分是数组总和的整数倍,剩下的一部分就是不能凑够一个数组的# res = len(nums) * (target // sum(nums))  # 数组总和的整数倍# target = target % sum(nums)  # 找到这个目标值的最小子数组# left, ans = 0, inf# nums = nums * 2  # 由于是无限数组,避免有尾和头拼接的情况,所以这里将两个数组拼接# for right, x in enumerate(nums):#     target -= x#     while target < 0:#         target += nums[left]#         left += 1#     if target == 0:#         ans = min(ans, right - left + 1)# return ans + res if ans != inf else -1# 也可以不开辟两个数组空间,用取模的方式res = len(nums) * (target // sum(nums))  # 数组总和的整数倍target = target % sum(nums)  # 找到这个目标值的最小子数组left, ans = 0, inffor right in range(len(nums) * 2):target -= nums[right % len(nums)]while target < 0:target += nums[left % len(nums)]left += 1if target == 0:ans = min(ans, right - left + 1)return ans + res if ans != inf else -1


76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 ""

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

示例 3:

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

class Solution:def minWindow(self, s: str, t: str) -> str:from collections import Counter# 计算t字符的个数win = Counter(t)left, ans, count = 0, "", inffor right, x in enumerate(s):if x in win:win[x] -= 1# 如果窗口内涵盖了t字符,就可以缩小窗口,同时也能收割结果while all([win[i] <= 0 for i in win]):if count > right - left + 1:    # 收割结果ans = s[left : right + 1]count = right - left + 1if s[left] in win:  # 缩小窗口win[s[left]] += 1left += 1return ans


632. 最小区间

你有 k非递减排列 的整数列表。找到一个 最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。

我们定义如果 b-a < d-c 或者在 b-a == d-ca < c,则区间 [a,b][c,d] 小。

示例 1:

输入:nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出:[20,24]
解释: 
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。

示例 2:

输入:nums = [[1,2,3],[1,2,3],[1,2,3]]
输出:[1,1]

class Solution:# 将几个数组合并在一起,并且构建一个二维列表,每个列表的第一个值是原来的元素,第二个值表示在第几个列表上的索引def smallestRange(self, nums: List[List[int]]) -> List[int]:from collections import defaultdictwin = defaultdict(int)  # 存储窗口内元素是在原来的第几个列表上的出现次数n = len(nums)nums = [[j, i] for i in range(len(nums)) for j in nums[i]]nums.sort()left = 0ans_l, ans_r = nums[0][0], nums[-1][0]for right, x in enumerate(nums):win[x[1]] += 1# 如果窗口内元素在每个列表中都出现了,则缩小窗口,同时收割结果while len(win) == n:if nums[right][0] - nums[left][0] < ans_r - ans_l:ans_l, ans_r = nums[left][0], nums[right][0]  # 收割结果win[nums[left][1]] -= 1  # 缩小窗口if win[nums[left][1]] == 0:del win[nums[left][1]]left += 1return [ans_l, ans_r]

相关文章:

  • 【quantity】11 体积单位模块(volume.rs)
  • Kubernetes(k8s)学习笔记(五)--部署Ingress实现域名访问和负载均衡
  • C++23 std::tuple与其他元组式对象的兼容 (P2165R4)
  • 每天五分钟深度学习框架PyTorch:基于Dataset封装自定义数据集
  • 用哈希表封装出unordered_set/_map
  • MySQL基础关键_007_DQL 练习
  • MOS管极间电容参数学习
  • 华中科技大学系统结构慕课部分答案
  • 250504_VsCode使用
  • Mybatis执行流程知多少
  • WEB 前端学 JAVA(二)Java 的发展与技术图谱简介
  • Linux网络编程:套接字
  • Spring AI支持的聊天模型全方位比较与分析
  • 利用n8n、DeepSeek、AI Agent、子工作流生成统计图
  • PyTorch_张量形状操作
  • 常用命令集合
  • 55、【OS】【Nuttx】编码规范解读(三)
  • 比较 TensorFlow 和 PyTorch
  • 30.沿触发控制与电平宽度触发控制的抗干扰能力对比分析
  • 如何在服务器后台运行Python脚本,并配置虚拟环境与GPU支持
  • 外交部亚洲司司长刘劲松就日本民用飞机侵闯我钓鱼岛领空向日方提出严正交涉
  • 马上评|提供情绪价值,也是文旅经济的软实力
  • 央行就《关于规范供应链金融业务引导供应链信息服务机构更好服务中小企业融资有关事宜的通知》答问
  • 新型算法助力听障人士听得更清晰
  • 美国参议院投票通过戴维·珀杜出任美国驻华大使
  • 黄仁勋访华期间表示希望继续与中国合作,贸促会回应