最近比较艰难啊,不足的地方好多,就当是打怪升级路漫漫了
我们统一思路都是:
- while里针对right作出改变
- 判断特殊条件是否满足,(如果窗口不固定在这步移动left)
- 每步right都要走,(如果固定窗口在这步移动left)
这样就可以做一个无情的代码机器(不用考虑滑动窗口现在的是框住的还是下一个的条件之类的,无脑刷就完事了)
类型一:滑动窗口固定
简单-643. 子数组最大平均数 I
求滑动窗口的最大平均数
中等-1423. 可获得的最大点数
说是从两边取最大,其实是求剩余最少,就是上一题求最大平均变成求和最小
567. 字符串的排列
比上面两道题难一些,要用到两个辅助空间,来判断模式串和滑动窗口是否匹配
中等-438. 找到字符串中所有字母异位词
上一题只要有全排列就返回true,这次要返回全部结果的开始
有点等待事件组那味了,也不知道实时系统最后会咋样,哎
class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
t =[0]*26
window =[0]*26
i = 0
if len (p) > len(s):
return []
for i in p:
t[ord(i)-ord('a')] += 1
left = 0
for j in range(len(p)-1):#因为while第一步就要走right,所以这边留一个
window[ord(s[j])-ord('a')] +=1
right = len(p)-1
n = len (s)
res =[]
while right < n:
window[ord(s[right])-ord('a')] += 1 #1.做出改变
if window == t: #2.特殊条件
res.append(left)
window[ord(s[left])-ord('a')] -= 1
left += 1#3.固定窗口都走路
right += 1
return res
类型二:滑动窗口只增不减
这种左脚只收一步
可替换求最长子数组,空间换时间
中等-1004. 最大连续1的个数 III
中等-424. 替换后的最长重复字符升级由0,1变成字母,思路换汤不换药
这里给个模版:
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
nums = [0] * 26
left = right = 0
n = len(s)
while right < n:
nums [ord(s[right]) - ord('A')] += 1#1.while里针对right作出改变
#试图扩张,结果失败 最大长度还是right-left
if max(nums) + k < right - left + 1: #2.条件满足走左脚
nums[ord(s[left]) - ord('A')] -= 1
left += 1
right += 1#3.右脚每步都要走
return right - left
类型三:滑动窗口会变小
这种左脚是个循环收脚
209. 中等-长度最小的子数组
给个模版:
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
left = right = 0
temp = 0
res = 100001
n = len(nums)
while right < n:
temp += nums[right]#1.while里针对right作出改变
while temp >= target:#2.条件满足走左脚
res = min(res , right - left +1 )
temp -= nums[left]
left += 1
right += 1#3.右脚每步都要走
if res == 100001:
return 0
return res
困难-76. 最小覆盖子串
这个题我用 中等-438. 找到字符串中所有字母异位词 和 209 的思路综合杂糅,哈希映射多了26,解起来着实变态,可以挑战一下,因为是应用模版思路,我就不看题解了…
class Solution:
def minWindow(self, s: str, t: str) -> str:
left = right = 0
window =[0] * 52
p = [0] * 52
flag = 0
for i in t:
k = ord(i)
if k<97:
p[k-ord('A')] += 1
else:
p[k-ord('a')+26] += 1
n = len(s)
res_left = res_right = 0
res_len =100001
while right < n:
if s[right] in t: #1.while里针对right作出改变
kk = ord(s[right])
if kk<97:
window[kk-ord('A')] += 1
else:
window[kk-ord('a')+26] += 1
#2.只要window的所有字符都>=p 就要收左脚
def check(a,b):
f = True
for i in range(min(len(a),len(b))):
if a[i] < b[i]:
f = False
return f
while check(window,p) and left<len(s):
flag = 1
if check(window,p):
if right - left + 1 < res_len:
res_left = left
res_right = right
res_len = right - left + 1
if s[left] in t:
k2 = ord(s[left])
if k2<97:
window[k2-ord('A')] -= 1
else:
window[k2-ord('a')+26] -= 1
left +=1
right += 1 #3.右脚每步都要走
if flag == 0:
return ""
return s[res_left:res_right+1]
3. 无重复字符的最长子串
做完其他的做这个不是敢敢单单啦~不过比较坑的是这边还有空格和符号,我本来遇到重复想直接刷新num,但是其实要一步步收左脚
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left = right = 0
nums = [0] * 1000
res = 0
if s== "":
return 0
while right < len(s):
nums[ord(s[right])] += 1
while nums[ord(s[right])] > 1:
res = max(res , right - left)
nums[ord(s[left])] -= 1
left += 1
right += 1
res = max(res , right - left)
return res
不收脚也可以呢
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
l,r = 0,0
dic = defaultdict(int)
while r < len(s):
dic[s[r]] += 1
if max(dic.values()) > 1:
dic[s[l]] -= 1
l += 1
r += 1
return r - l
最后是字节夏令营笔试
答主说是像3,我怎么感觉更像地狱76呢…
5.30 字节夏令营笔试题目
A. 题目描述
给定一个定长的字符串,其中包含若干字符,求该字符串中一个连续子串,满足两个条件:
- 子串包含该字符串中的所有不同的字符
- 满足条件1中最短的一个(若有多个,则找从左到右第一个出现的子串)
输出用子串的起始下标与长度来表示
输入描述:
输入一个字符串(如abbbaaccb),字符串长度[ 1, 65535],字符集为单字节ascii码集合
输出描述:
返回最短包含全集的子串,用(起始下标,长度)二元组表示。如果结果不唯一,返回第一个找到的结果。
上述例子中,候选有两个,即abb“baac”cb与abbba“accb”,返回第一个的子串,表示为( 3, 4)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
left = right = 0
nums = [0] * 128
window = [0] * 128
s = "abbbaaccb"
p = set(s)
for i in p:
nums[ord(i)] = 1
res = 100001
res_left = res_right = 0
def check(a,b):
for i in range(min(len(a),len(b))):
if a[i] < b[i]:
return False
return True
while right < len(s):
window [ord(s[right])] += 1
while check(window , nums):
if right - left + 1 < res:
res_left = left
res_right = right
res = right - left + 1
window [ord(s[left])] -= 1
left +=1
right += 1
return (res_left,res)
写到这里76确实是需要优化的……其实没那么难,但是我太懒啦,能过就优化,估计没太大可能,有缘再见咯~!!!