Python题解Leetcode Hot100之滑动窗口

滑动窗口题目的特点如下,经常用于解决字符串的子串问题

  1. 滑动窗口通过双指针指定窗口的左右边界;
  2. 通过某种数据结构存储窗口中的元素,数据结构的形式具体问题具体分析,经常是set、dict等;
  3. 窗口的右边界匀速扩张,而左边界通常是通过某种规律进行向右收缩;

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

  • 题目描述
    给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。
    示例 1:

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

    1. 看到子串,想到可以通过滑动窗口来解决;
    2. 看到无重复字符想到可以通过set来存储滑动窗口中的元素,可以快速查找当前元素是不是已经在窗口中;
    3. 滑动窗口从左往右滑动,如果当前元素不在窗口中,直接压入窗口中;如果已经在了,从左边开始弹出元素,直到当前元素不在窗口中,再将元素压入窗口中。这样保证窗口中的元素都是不重复的,那么统计窗口大小的最大值就是最长无重复子串的长度。
  • 代码

    class Solution:
        def lengthOfLongestSubstring(self, s: str) -> int:
            n = len(s)
            if n == 0:
                return 0
            chars = set()
            i = 0
            res = 0
            for j in range(n):
                if s[j] not in chars:
                    chars.add(s[j])
                else:
                    while s[j] in chars:
                        chars.remove(s[i])
                        i += 1
                    chars.add(s[j])
                # 每完成一次元素更新后,更新最大长度
                res = max(res, j - i + 1)
            return res
    

2. 找到字符串中所有字母异位词

  • 题目描述
    给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。
    异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。
  • 解题思路
    1. 本题仍然是寻找子串问题,可以用滑动窗口来解决;
    2. 看到字母异位词就想到可以通过dict来存储窗口中元素出现的次数;
    3. 本题中的窗口长度是确定的,利用这个限制条件可以找到符合要求的答案;
    4. 时间复杂度:
      具体的操作可见下面代码中的注释
  • 代码
    class Solution:
        def findAnagrams(self, s: str, p: str) -> List[int]:
            n = len(s)
            if n == 0:
                return []
            dic_p = {}
            for char in p:
                dic_p[char] = dic_p.get(char, 0) + 1
            dic_w = {}
            i = 0
            res = []
            for j in range(n):
                if len(dic_w) == 0:
                    i = j
                if s[j] in dic_p:
                    # 如果当前字符在p中,而且字符在窗口中的数量是符合条件的,那么将该字符加入窗口中
                    if dic_w.get(s[j], 0) < dic_p[s[j]]:
                        dic_w[s[j]] = dic_w.get(s[j], 0) + 1
                    else:
                        # 如果加上当前的字符后,当前的字符在窗口中的数量已经超过了p中的数量,那么将窗口左边界右移,直到窗口中的字符数量符合要求
                        while dic_w.get(s[j], 0) >= dic_p[s[j]]:
                            dic_w[s[i]] -= 1
                            i += 1
                        dic_w[s[j]] = dic_w.get(s[j], 0) + 1
                    # 上面的代码保证了字母的计数是满足要求的,如果此时窗口长度等于p的长度,说明找到了一个符合条件的子串
                    if j - i + 1 == len(p):
                        res.append(i)
                else:
                    # 如果出现了一个没有在p中的字符,那么将该窗口清除,重新开始计数
                    dic_w = {}
                    
            return res
    
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值