力扣刷题Python笔记:最小覆盖子串

题目

给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。
在这里插入图片描述
提示:
①如果 S 中不存这样的子串,则返回空字符串 “”
②如果 S 中存在这样的子串,我们保证它是唯一的答案

来源:力扣(LeetCode)

Python解法

滑动窗口解法

这道题想了半天也没有想出来,最后看了题解,发现思路不难,但是代码实现起来是真的难写~

以下解题思路和代码均来自力扣题解。
解题思路如下:
用 left、right 表示滑动窗口的左边界和右边界,通过改变 left、right 来扩展和收缩滑动窗口,可以想象成一个窗口在字符串上游走,当这个窗口包含的元素满足条件,即包含字符串 t 的所有元素,记录下这个滑动窗口的长度 right-left+1,这些长度中的最小值就是要求的结果。

具体如下:
①不断增加 right 使滑动窗口增大,直到窗口包含了字符串 t 的所有元素;
②不断增加 left 使滑动窗口缩小,因为是要求最小字串,所以将不必要的元素排除在外,使长度减小,直到碰到一个必须包含的元素,这个时候不能再扔了,再扔就不满足条件了,记录此时滑动窗口的长度,并保存最小值;
③让 left 再增加一个位置,这个时候滑动窗口肯定不满足条件了,那么继续从①开始执行,寻找新的满足条件的滑动窗口,如此反复,直到j超出了字符串S范围。

代码如下:

def minWindow(self, s: str, t: str) -> str:
    import collections
    dict_t =collections.defaultdict(int)
    for i in t:
        dict_t[i] += 1
    all_need = len(t)
    left = 0
    result = (0, float('inf'))
    for right, s_i in enumerate(s):
        if dict_t[s_i] > 0:
            all_need -= 1
        dict_t[s_i] -= 1
        if all_need == 0:
            while True:
                cur = s[left]
                if dict_t[cur] == 0:
                    break
                dict_t[cur] += 1 
                left += 1
            if right-left < result[1]-result[0]:
                result = (left, right)
            dict_t[s[left]] += 1
            all_need += 1
            left += 1
    return "" if result[1]-result[0] > len(s) else s[result[0]:result[1]+1]
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页