• 【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
    博文转载请注明出处。
  • 相关阅读:
    201521123004 《Java程序设计》第10周学习总结
    201521123004《Java程序设计》第9周学习总结
    201521123004《Java程序设计》第8周学习总结
    201521123004 《Java程序设计》第7周学习总结
    201521123004《Java程序设计》第6周学习总结
    201521123004《Java程序设计》第5周学习总结
    一个markdown的例子
    201521123004《Java程序设计》第4周学习总结
    201521123004 《Java程序设计》第3周学习总结
    Alpha阶段项目复审
  • 原文地址:https://www.cnblogs.com/EstherLjy/p/14607951.html
Copyright © 2020-2023  润新知