# 滑动窗口算法框架
class Solution:
def slidingWindow(self, s: str, p: str):
left = right = 0
needs, window = {}, {}
match = 0
for v in p: needs[v] = needs.get(v, 0) + 1
while right < len(s):
cur = s[right]
# 进行窗口内数据的一系列更新
if needs.get(cur):
window[cur] = window.get(cur, 0) + 1
if window[cur] == needs[cur]: match += 1
right += 1
# 判断左侧窗口是否要收缩
while (window needs shrink):
# 当窗口符合条件时,执行相应操作
cur = s[left]
# 进行窗口内数据的一系列更新
if needs.get(cur):
if window[cur] == needs[cur]: match -= 1
window[cur] -= 1
left += 1
给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 “” 。
注意:
示例 1:
输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。
import math
class Solution:
def minWindow(self, s: str, t: str) -> str:
left = right = 0
needs, window = {}, {}
smallest_len, smallest_str = math.inf, ""
# 记录 window 中已经有多少字符符合要求了
match = 0
for v in t: needs[v] = needs.get(v, 0) + 1
while right < len(s):
cur = s[right]
if needs.get(cur):
window[cur] = window.get(cur, 0) + 1
# 注意这里是 ==, 不是>=, 因为match是算A、B、C存在即符合条件
# 如果>=,两个B一个C没有A, match也是3,但其实只有一个A、一个B、一个C才算match
if window[cur] == needs[cur]: match += 1
# 注意这里的right其实是多加了1的
right += 1
while match == len(needs):
# 因为上面right多加1,因此原本这里的right - left + 1, 这里只需要right - left即可
cur_len = right - left
if cur_len < smallest_len:
smallest_len = cur_len
# 因为上面right多加1,因此原本这里的s[left:right + 1], 这里只需要s[left:right]即可
smallest_str = s[left:right]
cur = s[left]
if needs.get(cur):
if window[cur] == needs[cur]: match -= 1
window[cur] -= 1
left += 1
return smallest_str
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
示例 1:
输入: s = "cbaebabacd", p = "abc"
输出: [0,6]
解释:
起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。
起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
left = right = 0
needs, window = {}, {}
res = []
match = 0
for v in p: needs[v] = needs.get(v, 0) + 1
while right < len(s):
cur = s[right]
# 进行窗口内数据的一系列更新
if needs.get(cur):
window[cur] = window.get(cur, 0) + 1
if window[cur] == needs[cur]: match += 1
right += 1
# 判断左侧窗口是否要收缩
# 这个题比较特殊可以直接if, 也可以和解题框架保持一致使用:while (right - left) == len(p):
if (right - left) == len(p):
# 当窗口符合条件时,把起始索引加入 res
if match == len(needs):
res.append(left)
cur = s[left]
# 进行窗口内数据的一系列更新
if needs.get(cur):
if window[cur] == needs[cur]: match -= 1
window[cur] -= 1
left += 1
return res
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left = right = 0
window = {}
longest_len = 0
while right < len(s):
r = s[right]
window[r] = window.get(r, 0) + 1
right += 1
while window[r] > 1:
l = s[left]
window[l] -= 1
left += 1
# 没有重复的才计算最大长度
cur_len = right - left
longest_len = max(cur_len, longest_len)
return longest_len
给你两个字符串 s1 和 s2 ,写一个函数来判断 s2 是否包含 s1 的排列。如果是,返回 true ;否则,返回 false 。
换句话说,s1 的排列之一是 s2 的 子串 。
示例 1:
输入:s1 = "ab" s2 = "eidbaooo"
输出:true
解释:s2 包含 s1 的排列之一 ("ba").
class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
left = right = 0
needs, window = {}, {}
flag = False
match = 0
for v in s1: needs[v] = needs.get(v, 0) + 1
while right < len(s2):
r = s2[right]
if needs.get(r):
window[r] = window.get(r, 0) + 1
if window[r] == needs[r]: match += 1
right += 1
if (right - left) == len(s1):
if match == len(needs):
flag = True
break
l = s2[left]
if needs.get(l):
if window[l] == needs[l]: match -= 1
window[l] -= 1
left += 1
return flag