滑动窗口-文本序列

**1. 无重复最长子串**
子串的话肯定是连续的序列,设置一个集合,遍历每一个字符,当这个字符在集合中的话,删除的是从左到这个字符的所有元素。如果不重复就加入到集合中。
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if not s: return 0
        left = 0
        lookup = set()
        n = len(s)
        max_len = 0
        cur_len = 0
        for i in range(n):
            cur_len += 1
            while s[i] in lookup:
                lookup.remove(s[left])
                left += 1
                cur_len -= 1
            if cur_len > max_len : max_len = cur_len
            lookup.add(s[i])
        return max_len

s = Solution()
print(s.lengthOfLongestSubstring('abcabcbb'))

**2. 串联所有单词的子串**
# 给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
#
# 注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
#
# 输入:
#   s = "barfoothefoobarman",
#   words = ["foo","bar"]
# 输出:[0,9]
# 解释:
# 从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。
# 输出的顺序不重要, [9,0] 也是有效答案。

#思路:在字符串上移动长度为words长的窗口,步长为1遍历。
#如何去判断子串也是难点 再定义一个滑动窗口,长度为每个单词的长度(因为每个单词等长)将待检测的单词用一个字典表示,key代表单词 value代表数目。
#定义一个字典,如果检测到了就加到字典中 key为检测单词,value为数目。当value中的数目大于之前字典中单词value时,说明不符合,反之依次遍历步长为每个单词的长度。
from collections import Counter, defaultdict
class Solution(object):
    def findSubstring(self, string, words):
        output = []
        if not string or not words:
            return output
        single_len = len(words[0])
        words_len = len(words) * single_len #第一个滑动窗口的长度
        for step in range(len(string) - words_len + 1):
            wordstr = string[step: step + words_len] #每次截取的值
            if self.judge(wordstr, words):
                output.append(step)
        return output
    def judge(self, wordstr, words): #words 为题目中查找的词
        single_word = len(words[0])
        original = Counter(words) #统计words
        count_dict = defaultdict(int)
        for word_index in range(0, len(wordstr) , single_word): #single_word为滑动窗口步长,
            new_word = wordstr[word_index:word_index + single_word]
            if new_word in list(original.elements()): #如果滑动值在words中
                count_dict[new_word] += 1
                if count_dict[new_word] > original[new_word]:
                    return False
            else:
                return False
        # for word, count in dict(original).items():
        #     if count != count_dict[word]:
        #         return False
        if original != count_dict:
            return False
        return True

if __name__ == '__main__':
    s = Solution()
    a = s.findSubstring("a",  ["a"])
    print(a)
**利用列表表达式**
from collections import Counter
class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if not words: return []
        pattern=Counter(words)
        res=[]
        wsLen=len(words)
        wLen=len(words[0])
        for i in range(len(s)-wLen*wsLen+1):
            cur=[s[i+j*wLen:i+(j+1)*wLen] for j in range(wsLen)]
            if Counter(cur)==pattern: res.append(i)
        return res

**最小覆盖字符串**
from collections import Counter
class Solution:

    def minWindow(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        if not t or not s:
            return ""

        # Dictionary which keeps a count of all the unique characters in t.
        dict_t = Counter(t)

        # Number of unique characters in t, which need to be present in the desired window.
        required = len(dict_t)

        # left and right pointer
        l, r = 0, 0

        # formed is used to keep track of how many unique characters in t are present in the current window in its desired frequency.
        # e.g. if t is "AABC" then the window must have two A's, one B and one C. Thus formed would be = 3 when all these conditions are met.
        formed = 0

        # Dictionary which keeps a count of all the unique characters in the current window.
        window_counts = {}

        # ans tuple of the form (window length, left, right)
        ans = float("inf"), None, None

        while r < len(s):

            # Add one character from the right to the window
            character = s[r]
            window_counts[character] = window_counts.get(character, 0) + 1

            # If the frequency of the current character added equals to the desired count in t then increment the formed count by 1.
            if character in dict_t and window_counts[character] == dict_t[character]:
                formed += 1

            # Try and contract the window till the point where it ceases to be 'desirable'.
            while l <= r and formed == required:
                character = s[l]

                # Save the smallest window until now.
                if r - l + 1 < ans[0]:
                    ans = (r - l + 1, l, r)

                # The character at the position pointed by the `left` pointer is no longer a part of the window.
                window_counts[character] -= 1
                if character in dict_t and window_counts[character] < dict_t[character]:
                    formed -= 1

                # Move the left pointer ahead, this would help to look for a new window.
                l += 1

            # Keep expanding the window once we are done contracting.
            r += 1
        return "" if ans[0] == float("inf") else s[ans[1] : ans[2] + 1]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值