LC DFS


DFS Algorithms

最小覆盖子串

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

def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        ls = len(s)
        lt = len(t)
        start = 0
        end = 0
        minl = float('inf')
        res1 = 0
        res2 = 0
        dic = {}
        for c in t:
            dic[c] = dic.get(c, 0) + 1
        window = {}
        for c in t:
            window[c] = 0
        valid = 0
        # 一般而言,[left, right)/[start, end)的窗口比较大众,因为默认end得往后走一位,打印的时候确实不包括end
        while end < ls:
            tmp = s[end]
            # 更新窗口向右移动之后的window情况
            if tmp in window:
                window[tmp] += 1
                # 如果t中对应的某个元素有两个,那么只有当其满足两个的时候才会+1
                # 但是实际上,应该是找到一个就+1捏,但是这样又会导致tmp一直等于某一个数使得valid疯狂自增
                # 因此必须是小于等于的时候就可以增加valid了
                if window[tmp] <= dic[tmp]:
                    valid += 1
            # end什么时候+1也有说法
            end += 1

            # debug专用,找到移动规律
            # print(start, end)

            # 当窗口需要收缩,左边需要减小
            while valid == lt:
                # 在这里更新最小的覆盖字串
                if end - start < minl:
                    res1 = start
                    # 说实话长度这里必须必须注意end的意义,左闭右开
                    res2 = end - start
                    minl = res2
                # 先提取出将要被剔除出窗口的元素,start什么时候+1都行,但得先取值
                d = s[start]
                start += 1
                if window.get(d):
                    if window[d] == dic[d]:
                        valid -= 1
                    window[d] -= 1


        if res2:
            return s[res1:res1+res2]
        else:
            return ''

找到字符串中所有字母异位词

给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

异位词 指由相同字母重排列形成的字符串(包括相同的字符串)。

ls = len(s)
start = 0
end = 0
valid = 0
res = []
dic = {}
for c in p:
    dic[c] = dic.get(c, 0) + 1
window = {}
# window有个优化,就是到后面判定某字符在dic内,然后更新window,就不用重新遍历一次了
for c in p:
    window[c] = 0

while end < ls:
    tmp = s[end]
    # 更新窗口向右移动之后的window情况
    if tmp in window:
        window[tmp] += 1
        if window[tmp] <= dic[tmp]:
            valid += 1
    
    end += 1
    # debug专用,找到移动规律
    # print(start, end)
    # 当窗口需要收缩
    while valid == len(p):
        # 更新异位词的判断
        if end - start == len(p):
            res.append(start)

        d = s[start]
        start += 1

        if window.get(d):
            if window[d] == dic[d]:
                valid -= 1
            window[d] -= 1

    
return res

无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

ls = len(s)
start = 0
end = 0
maxl = 0
window = {}
jihe = set()

while end < ls:
    tmp = s[end]
    window[tmp] = window.get(tmp, 0) + 1
    
    end += 1
    # debug专用,找到移动规律
    # print(start, end)
    # 当窗口需要收缩
    while window[tmp] > 1:
        # 更新异位词的判断
        d = s[start]
        start += 1
        
        window[d] -= 1
    if end - start > maxl:
        maxl = end - start
    
return maxl

Author: cipher
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source cipher !
  TOC