LeetCode 76. Minimum Window Substring 题解

LeetCode 76. Minimum Window Substring 题解

题目描述

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果不存在符合条件的子串,则返回空字符串 "" 。

注意:

  • 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。
  • 如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"
解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

示例 2:

输入:s = "a", t = "a"
输出:"a"
解释:整个字符串 s 是最小覆盖子串。

解题思路

使用滑动窗口算法:

  1. 扩展右边界,直到窗口包含所有需要的字符
  2. 收缩左边界,找到最小的满足条件的窗口
  3. 重复直到右边界到达字符串末尾

代码实现

from collections import Counter

def minWindow(s, t):
    if not s or not t:
        return ""
    
    # 统计t中字符的需求
    need = Counter(t)
    required = len(need)
    
    # 窗口中的字符统计
    window = {}
    formed = 0
    
    left = 0
    min_len = float('inf')
    min_window = ""
    
    for right, char in enumerate(s):
        # 扩展窗口
        window[char] = window.get(char, 0) + 1
        
        if char in need and window[char] == need[char]:
            formed += 1
        
        # 收缩窗口
        while formed == required and left <= right:
            # 更新最小窗口
            if right - left + 1 < min_len:
                min_len = right - left + 1
                min_window = s[left:right+1]
            
            # 移除左边字符
            left_char = s[left]
            window[left_char] -= 1
            
            if left_char in need and window[left_char] < need[left_char]:
                formed -= 1
            
            left += 1
    
    return min_window

复杂度分析

  • 时间复杂度:O(|s| + |t|)
  • 空间复杂度:O(|s| + |t|)

优化版本

def minWindow(s, t):
    if not s or not t:
        return ""
    
    need = [0] * 128
    for c in t:
        need[ord(c)] += 1
    
    required = len(t)
    left = 0
    min_len = float('inf')
    min_start = 0
    
    for right, c in enumerate(s):
        if need[ord(c)] > 0:
            required -= 1
        need[ord(c)] -= 1
        
        while required == 0:
            if right - left + 1 < min_len:
                min_len = right - left + 1
                min_start = left
            
            left_char = s[left]
            need[ord(left_char)] += 1
            if need[ord(left_char)] > 0:
                required += 1
            left += 1
    
    return s[min_start:min_start+min_len] if min_len != float('inf') else ""

测试案例

# 测试案例 1
assert minWindow("ADOBECODEBANC", "ABC") == "BANC"

# 测试案例 2
assert minWindow("a", "a") == "a"

# 测试案例 3
assert minWindow("a", "aa") == ""

总结

本题是滑动窗口算法的经典难题。

关键点:

  • 使用哈希表或数组统计字符需求
  • 双指针维护滑动窗口
  • 在满足条件时收缩窗口找最优解
  • 注意重复字符的处理
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值