【力扣十道】彻底解决滑动窗口

最近比较艰难啊,不足的地方好多,就当是打怪升级路漫漫了
我们统一思路都是:

  1. while里针对right作出改变
  2. 判断特殊条件是否满足,(如果窗口不固定在这步移动left)
  3. 每步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. 子串包含该字符串中的所有不同的字符
  2. 满足条件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确实是需要优化的……其实没那么难,但是我太懒啦,能过就优化,估计没太大可能,有缘再见咯~!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值