【Leetcode】滑窗系列

【总结】

该类题目包括类型为:

1.最多包含k个重复字符的连续子串:【Leetcode-3】,窗口先增加后减少,窗口增加的条件是字符已经存在(look_up[a[end]]>0),窗口减少的条件是窗口内首字符是重复(look_up[a[start]]>1)

2.最多包含k个不同字符的连续子串:【Leetcode-340】,窗口先增加后减少,窗口增加的条件是字符新出现(look_up[a[end]]==0),窗口减少的条件是窗口内首字符只有1个(look_up[a[start]]==1)

3.至少包含某些字符的连续子串:【Leetcode-76】,窗口先减少后增加,窗口减少的条件是字符是被需要的(look_up[a[end]]>0),窗口增加的条件是窗口内首字符刚好够(look_up[a[start]]==0)

4.乘积至多/至少为k的的连续子串:【Leetcode-713】

  

Leetcode-3】

一、题目:无重复字符的最长子串

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

二、代码

def lengthOfLongestSubstring(self, s: str) -> int:
        from collections import defaultdict
        look_up = defaultdict(int)
        i = j = window = max_val = 0
        while j <= len(s) - 1:
            if look_up[s[j]] > 0:
                window += 1
            look_up[s[j]] += 1
            j += 1
            while window > 0:
                if look_up[s[i]] > 1:
                    window -= 1
                look_up[s[i]] -= 1
                i += 1
            max_val = max(max_val, j - i)
        return max_val

【Leetcode-159】

一、题目:至多包含两个不同字符的最长子串

  给定一个字符串 s ,找出 至多 包含两个不同字符的最长子串 t ,并返回该子串的长度。

二、代码:

def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
        """
        滑窗,窗口先大再小,大的条件是来了新字符,小的条件是该字符只出现一次
        """
        n = len(s)
        start = end = res = window = 0
        lookup = {} 
        while end < n:
            cnt = lookup.get(s[end], 0)
            if cnt == 0:
                window += 1
            lookup[s[end]] = cnt + 1
            end += 1
            while window > 2:
                cnt = lookup.get(s[start], 0)
                if cnt == 1:
                    window -= 1
                lookup[s[start]] = cnt - 1
                start += 1
            # 满足条件
            res = max(res, end-start)
        return res

【Leetcode-340】

一、题目:至多包含k个不同字符的最长子串

  给定一个字符串 s ,找出 至多 包含 k 个不同字符的最长子串 T

二、代码:

def lengthOfLongestSubstringKDistinct(self, s: str, k: int) -> int:
        from collections import defaultdict
        lookup = defaultdict(int)
        start = 0
        end = 0
        max_len = 0
        counter = 0
        while end < len(s):
            if lookup[s[end]] == 0:
                counter += 1
            lookup[s[end]] += 1
            end += 1
            while counter > k:
                if lookup[s[start]] == 1:
                    counter -= 1
                lookup[s[start]] -= 1
                start += 1
            max_len = max(max_len, end - start)
        return max_len

【Leetcode-76】最小覆盖子串

一、题目:

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

二、代码:

def minWindow(self, s: 'str', t: 'str') -> 'str':
        from collections import defaultdict
        lookup = defaultdict(int)
        for c in t:
            lookup[c] += 1
        start = 0
        end = 0
        min_len = float("inf")
        counter = len(t)
        res = ""
        while end < len(s):
            if lookup[s[end]] > 0:
                counter -= 1
            lookup[s[end]] -= 1
            end += 1
            while counter == 0:
                if min_len > end - start:
                    min_len = end - start
                    res = s[start:end]
                if lookup[s[start]] == 0:
                    counter += 1
                lookup[s[start]] += 1
                start += 1
        return res

【Leetcode-713】

一、题目:乘积小于K的子数组

  给定一个正整数数组 nums

  找出该数组内乘积小于 k 的连续的子数组的个数。

二、代码:

def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
        """
        前缀积,0~i的乘积为si,前缀积记录在look,则截止到i(包括i),<k的连续子数组数为look中key>si/k的数量之和+自身是否>k
        !当数值可能较大时,前缀积也较大,可能无法计算,因此该方法只能数值小时使用!
        if k == 0:
            return 0
        look = {1: 1}
        pre_multi = 1
        res = 0
        for item in nums:
            pre_multi *= item
            # 前面提供的
            for pre, ct in look.items():
                if pre > pre_multi/k:
                    res += ct 
            # 更新
            cnt = look.get(pre_multi, 0)
            look[pre_multi] = cnt + 1
        return res
        """
        """
        滑窗
        """
        if k <= 1:
            return 0
        accumulate = 1  # 窗口内的积
        n = len(nums)
        res = 0
        start, end = 0, 0  # 窗口两端,结果需要包含end
        while end < n:
            accumulate *= nums[end]
            end += 1
            while accumulate >= k:
                accumulate /= nums[start]
                start += 1
            # 此刻满足条件,记录个数
            res += (end - start)  # start~end-1间,包含end的子数组个数
        return res
博文转载请注明出处。
原文地址:https://www.cnblogs.com/EstherLjy/p/14607951.html