【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串

简介: 【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串

一般应用场景

数组,字符串子串等问题。

通用模板

双指针大致逻辑如下:

left = 0
right  = 0
while  right < len(s):
    # 右指针右移增大窗口
    window.add(s[right])
    right  += 1
    while isvalid:
        # 当满足某种条件时开始从左边收缩窗口
        window.remove(s[left])
        left += 1

代码模板:

def slidingWindow(s, t):
    from collections import defaultdict
    # defaultdict(int)对于不存在的键默认值为0,
    # 可以直接进行window[c] += 1的操作,免去了判断过程
    window = defaultdict(int)
    needs  = defaultdict(int)
    left = 0
    right = 0
    for c in t:
        needs[c] += 1
    while right < len(s):
        # c1为移入窗口的字符
        c1 = s[right]
        # 窗口右移
        right += 1
        # 进行窗口内数据的相关操作
        # TODO
        # 判断左侧窗口是否要收缩
        while window needs shrink:
            # c2为将要移出窗口的字符
            c2 = s[left]
            # 左指针右移,收缩窗口
            left += 1
            # 进行窗口内数据的相关操作
            # TODO

相关Leetcode题目

  1. 最小覆盖子串

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        from collections import defaultdict
        needs = defaultdict(int)
        window = defaultdict(int)
        left = 0
        right = 0
        count = 0 #window中满足条件的字符数
        start = 0 #记录最小子串的起始位置
        min_len = float('inf') #记录最小子串的长度
        for c in t:
            needs[c] += 1
        while right < len(s):
            c1 = s[right]
            right += 1
            if  c1 in needs:
                window[c1] += 1
                if window[c1] == needs[c1]:
                    count += 1
            while count == len(needs):
                # 更新最小覆盖子串
                if right - left < min_len:
                    start = left
                    min_len = right - left
                c2 = s[left]
                left += 1
                if c2 in needs:
                    window[c2] -= 1
                    if window[c2] < needs[c2]:
                        count -= 1
        if min_len == float('inf'):
            return ''
        else:
            return s[start:start+min_len]
  1. 字符串排列

class Solution:
    def checkInclusion(self, s1: str, s2: str) -> bool:
        from collections  import defaultdict
        needs = defaultdict(int)
        for c in s1:
            needs[c] += 1
        window = defaultdict(int)
        left = 0
        right = 0
        count = 0
        while right < len(s2):
            c1 = s2[right]
            right += 1
            if c1 in needs:
                window[c1] += 1
                if window[c1] == needs[c1]:
                    count += 1
            while count == len(needs):
                if right - left == len(s1):
                    # 如果子串长度与s1相等则包含
                    return True
                c2 = s2[left]
                if c2 in needs:
                    window[c2] -= 1
                    if window[c2] < needs[c2]:
                        count -= 1
                left += 1
        return False
  1. 找所有字母异位词

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        from collections import defaultdict
        needs = defaultdict(int)
        window = defaultdict(int)
        left = 0
        right = 0
        count = 0
        res = []
        for c in p:
            needs[c] += 1
        while right < len(s):
            c1 = s[right]
            if c1 in needs:
                window[c1] += 1
                if window[c1] == needs[c1]:
                    count += 1
            right += 1
            while count == len(needs):
                if right - left == len(p):
                    res.append(left)
                c2 = s[left]
                if c2 in needs:
                    window[c2] -= 1
                    if window[c2] < needs[c2]:
                        count -= 1
                left += 1
        return res
  1. 最长无重复子串

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        max_len = 0
        left = 0
        right = 0
        n = len(s)
        from collections import defaultdict
        window = defaultdict(int)
        while right < n:
            c1 = s[right]
            right += 1
            window[c1] += 1
            while window[c1] > 1:
                c2 = s[left]
                left += 1
                window[c2] -= 1
            max_len = max(max_len, right - left)
        return max_len


相关文章
|
5天前
|
算法 Java
[Java·算法·简单] LeetCode 283. 移动零
[Java·算法·简单] LeetCode 283. 移动零
15 2
|
8天前
|
存储 算法 调度
力扣中级算法(Python)
力扣中级算法(Python)
|
8天前
|
算法 Python
力扣初级算法(Python)(二)
力扣初级算法(Python)(二)
|
8天前
|
算法 Python
力扣初级算法(Python)(一)
力扣初级算法(Python)(一)
|
9天前
|
算法
【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)
【LeetCode刷题】滑动窗口解决问题:串联所有单词的子串(困难)、最小覆盖子串(困难)
|
9天前
|
算法 容器
【LeetCode刷题】滑动窗口解决问题:水果成篮、找到字符串中所有字母异位词
【LeetCode刷题】滑动窗口解决问题:水果成篮、找到字符串中所有字母异位词
|
9天前
|
算法
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
|
1天前
|
人工智能 算法 搜索推荐
蓝桥杯宝藏排序题目算法(冒泡、选择、插入)
以下是内容的摘要: 本文介绍了三种排序算法:冒泡排序、选择排序和插入排序。冒泡排序通过不断交换相邻的逆序元素逐步排序,最坏情况下需要 O(n^2) 次比较。选择排序在每轮中找到剩余部分的最小元素并放到已排序序列的末尾,同样具有 O(n^2) 时间复杂度。插入排序则是将每个元素插入到已排序序列的正确位置,时间复杂度也是 O(n^2),但空间复杂度为 O(1)。
|
2天前
|
算法
基于蝗虫优化的KNN分类特征选择算法的matlab仿真
摘要: - 功能:使用蝗虫优化算法增强KNN分类器的特征选择,提高分类准确性 - 软件版本:MATLAB2022a - 核心算法:通过GOA选择KNN的最优特征以改善性能 - 算法原理: - KNN基于最近邻原则进行分类 - 特征选择能去除冗余,提高效率 - GOA模仿蝗虫行为寻找最佳特征子集,以最大化KNN的验证集准确率 - 运行流程:初始化、评估、更新,直到达到停止标准,输出最佳特征组合
|
3天前
|
机器学习/深度学习 算法 数据挖掘
【机器学习】Voting集成学习算法:分类任务中的新利器
【机器学习】Voting集成学习算法:分类任务中的新利器
10 0