返回

算法进阶:寻找最小覆盖子串

前端

记一道算法题:最小覆盖子串

题目:

给定两个字符串 st,找到 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在这样的子串,则返回空字符串 ""

示例:

输入:s = "ADOBECODEBANC", t = "ABC"
输出:"BANC"

在上面的例子中,"BANC"s 中涵盖 t 所有字符的最小子串。

算法分析:

最小覆盖子串问题的关键在于找到一个涵盖 t 所有字符的最小子串。我们可以使用滑动窗口法来解决这个问题。滑动窗口法是一种贪心算法,它通过不断调整窗口的范围来找到最优解。

具体来说,我们可以先初始化一个窗口,并将窗口内的字符与 t 中的字符进行比较。如果窗口内的字符涵盖了 t 中的所有字符,那么这个窗口就是候选子串。然后,我们将窗口向右移动一个字符,并重复这个过程,直到找到最小的候选子串。

代码实现:

def min_window(s, t):
    """
    找到 s 中涵盖 t 所有字符的最小子串

    Args:
        s (str): 输入字符串
        t (str): 目标字符串

    Returns:
        str: 最小子串
    """

    # 初始化窗口和字符计数
    window = {}
    target = {}
    for char in t:
        target[char] = target.get(char, 0) + 1

    # 滑动窗口
    left = 0
    right = 0
    min_window_size = float('inf')
    min_window = ""

    # 满足条件的字符数
    matched = 0

    while right < len(s):
        # 将右边界字符添加到窗口中
        char = s[right]
        window[char] = window.get(char, 0) + 1

        # 更新满足条件的字符数
        if char in target and window[char] <= target[char]:
            matched += 1

        # 当满足条件的字符数等于目标字符数时,开始收缩窗口
        while matched == len(target):
            # 更新最小窗口
            window_size = right - left + 1
            if window_size < min_window_size:
                min_window_size = window_size
                min_window = s[left:right+1]

            # 将左边界字符从窗口中移除
            char = s[left]
            window[char] -= 1

            # 更新满足条件的字符数
            if char in target and window[char] < target[char]:
                matched -= 1

            # 收缩窗口
            left += 1

        # 扩展窗口
        right += 1

    return min_window

结语:

最小覆盖子串问题是一个经典的算法问题,它在字符串处理、文本搜索等领域都有着广泛的应用。通过这篇文章,您已经对最小覆盖子串问题有了一个深入的了解,并且掌握了使用滑动窗口法来解决该问题的技巧。希望这篇文章能够帮助您在算法学习的道路上更进一步。