📜  门| GATE CS 2018 |简体中文问题18(1)

📅  最后修改于: 2023-12-03 14:58:20.143000             🧑  作者: Mango

门 | GATE CS 2018 | 简体中文问题18

本文主要介绍 GATE CS 2018 中的问题18,涉及到程序的数据结构和算法。

问题描述

给定一个字符串 S 和一个字符集 C,找到 S 中最短的子串,其包含 C 中的所有字符。例如,如果 S = "ADOBECODEBANC" 而 C = "ABC",则要求的子串为 "BANC"。

解法分析

这是一个非常经典的问题,可以使用滑动窗口算法来解决。定义左右指针 left, right 分别指向字符串 S 的起始位置,同时维护一个计数器 count 记录当前已找到的字符集 C 中包含的字符数目。

我们先向右移动指针 right,直到找到包含 C 中所有字符的子串为止。此时,我们可以记录子串的长度 len,并尝试将指针 left 向右移动,直到不能再移动为止。

在移动 left 的过程中,需要同时更新计数器 count,每当遇到一个包含在 C 中的字符时,将计数器 count 减1。当计数器 count 为 0 时,表示当前子串已包含所有字符,可以记录下当前的子串长度 len,并继续向右移动指针 right。

在移动 left 和 right 的过程中,可以不断更新最短子串的长度,并记录其起始位置 start。当 right 指向字符串 S 的末尾时,得到的子串就是最短的子串。

时间复杂度为 O(n),其中 n 是字符串 S 的长度。

以下是该算法的 Python 代码实现:

def min_window(s: str, t: str) -> str:
    need, window = {}, {}
    for c in t:
        need[c] = need.get(c, 0) + 1
    left, right, valid = 0, 0, 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]

其中,need 用于记录字符集 C 中的字符,window 用于记录当前窗口中的字符。left, right 分别记录窗口的左右边界,valid 记录已经匹配的字符数目,start 记录最短子串的起始位置,length 记录最短子串的长度。