【力扣hot100】滑动窗口-最小覆盖子串

题目描述

给定两个字符串 s 和 t,长度分别是 m 和 n,返回 s 中的 最短窗口 子串,使得该子串包含 t 中的每一个字符(包括重复字符)。如果没有这样的子串,返回空字符串 ""。

测试用例保证答案唯一。

示例 1:

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

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

输入: s = "a", t = "aa"
输出: ""
解释: t 中两个字符 'a' 均应包含在 s 的子串中,
因此没有符合条件的子字符串,返回空字符串。

代码实现

func minWindow(s string, t string) string {
    if len(s) == 0 || len(t) == 0 || len(s) < len(t) {
        return ""
    }

    need := make(map[byte]int)
    window := make(map[byte]int)
    for _, ch := range t {
    	need[ch]++
    }

    left, right := 0, 0
    minLen := len(s) + 1
    start := 0
    valid := 0
    for right < len(s) {
    	//扩张边界
    	c := s[right]
    	right++
    	//更新窗口
    	if c, ok := need[c];ok {
    		window[c]++
    		if window[c] == need[c] {
    			valid++
    		}
    	}

    	//如果valid == len(need) 尝试收缩左边界
    	for valid == len(need) {
    		if right - left < minLen {
    			start = left
    			minLen = right - left
    		}

    		//收缩左边界
    		d := s[left]
    		left++
    		//计数--
    		if _, ok := need[d]; ok {
    			if window[d] == need[d] {
    				valid--
    			}
    			window[d]--
    		}
    	}
    }
    if minLen == len(s) + 1 {
    	return ""
    }
    return s[start: start + minLen]
}

posted @ 2026-04-20 22:18  干炸小黄鱼  阅读(13)  评论(0)    收藏  举报