Minimum Window Substring,LeetCode,76

题目描述

给定一个字符串 S 和一个字符串 T,请在字符串 S 中找出包含 T 中所有字符的最小子串。

示例

输入: S = "ADOBECODEBANC", T = "ABC" 输出: "BANC"

说明

  • 如果 S 中不存这样的子串,则返回空字符串 ""
  • 如果存在多个满足条件的最小子串,返回任意一个即可。

解题思路

这个问题可以通过滑动窗口(Sliding Window)的方法来解决。滑动窗口是一种常用的双指针技巧,适用于一维数组或字符串等线性结构。

具体步骤

  1. 初始化变量
    • 使用两个指针 leftright 表示滑动窗口的左右边界,初始都指向 S 的起始位置。
    • 使用一个字典 need 来记录字符串 T 中每个字符的需求量。
    • 使用一个字典 window 来记录当前窗口中每个字符的数量。
    • 使用一个变量 valid 来记录窗口中满足 T 中字符需求的字符数量。
  2. 扩展右边界
    • 移动 right 指针,将 S[right] 加入窗口,并更新 windowvalid
  3. 收缩左边界
    • 当窗口中的字符已经满足 T 的需求时,尝试收缩窗口,移动 left 指针,更新 windowvalid,并记录当前窗口的长度和起始位置。
  4. 更新最小窗口
    • 在收缩左边界的过程中,不断更新最小窗口的长度和起始位置。
  5. 返回结果
    • 根据记录的最小窗口长度和起始位置,返回最小窗口子串。

代码实现

def minWindow(s: str, t: str) -> str: need = {} window = {} for char in t: need[char] = need.get(char, 0) + 1

left, right = 0, 0
valid = 0
start, length = 0, float('inf')

while right < len(s):
    # 扩展右边界
    c = s[right]
    right += 1
    if c in need:
        window[c] = window.get(c, 0) + 1
        if window[c] == need[c]:
            valid += 1

    # 收缩左边界
    while valid == len(need):
        if right - left < length:
            start = left
            length = right - left

        d = s[left]
        left += 1
        if d in need:
            if window[d] == need[d]:
                valid -= 1
            window[d] -= 1

return "" if length == float('inf') else s[start:start + length]

示例

s = "ADOBECODEBANC" t = "ABC" print(minWindow(s, t)) # 输出: "BANC"

复杂度分析

  • 时间复杂度:O(N),其中 N 是字符串 S 的长度。每个字符最多被访问两次(一次被 right 指针访问,一次被 left 指针访问)。
  • 空间复杂度:O(|T|),其中 |T| 是字符串 T 的长度。主要是用于存储 needwindow 字典。

总结

滑动窗口是一种高效解决字符串子串问题的方法,通过双指针的移动来维护一个动态的窗口,并在窗口满足条件时进行收缩,从而找到满足条件的最小子串。这个方法在很多类似的问题中都有广泛的应用。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注