【Leetcode】滑窗系列
【总结】
1.该类题目包括类型为:1)最多包含k个重复(不重复)字符的连续子串 2)最少包含某些字符的连续子串 3)乘积/和至少/至多为k的连续子串
2.解题思路:分为最多包含和最少包含
def f(s): l, r = 0, 0 look_up = {} counter = 0 while r < len(s): look_up[s[r]] = look_up.get(s[r], 0) + 1 # 右指针填进去 if *: counter += 1 # 更新counter while *: # 移动左指针使得满足条件 look_up[s[l]] -= 1 # 左指针去除 if *: counter -= 1 # 更新counter l += 1 r += 1
def f(s): l, r = 0, 0 look_up = {} for item in t: look_up[item] = look_up.get(item, 0) + 1 counter = len(t) while r < len(s): look_up[s[r]] = look_up.get(s[r], 0) - 1 # 右指针填进去 if *: counter -= 1 # 更新counter while *: # 移动左指针使得不满足条件 look_up[s[l]] += 1 # 左指针去除 if *: counter += 1 # 更新counter l += 1 r += 1
【Leetcode-3】
一、题目:无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
二、代码
def lengthOfLongestSubstring(self, s: str) -> int: """ look_up记录窗口里元素的数量,counter记录至少剔除几个元素才能不重复 """ l, r = 0, 0 max_len = 0 look_up = {} counter = 0 while r < len(s): look_up[s[r]] = look_up.get(s[r], 0) + 1 # 右指针填进去 if look_up[s[r]] > 1: counter += 1 # 重复+1 while counter > 0: # 移动左指针去除重复 look_up[s[l]] -= 1 if look_up[s[l]] >= 1: # 现在依然有1个,说明之前是重复 counter -= 1 l += 1 max_len = max(r-l+1, max_len) r += 1 return max_len """ 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-76】最小覆盖子串
一、题目:
给你一个字符串 s
、一个字符串 t
。返回 s
中涵盖 t
所有字符的最小子串。如果 s
中不存在涵盖 t
所有字符的子串,则返回空字符串 ""
。
二、代码:
def minWindow(self, s: str, t: str) -> str: """ look_up表示窗口里面需要元素的数量,counter表示最少需要的元素个数 """ l, r = 0, 0 look_up = {} for item in t: look_up[item] = look_up.get(item, 0) + 1 counter = len(t) res = [-1, float('inf')] # 起点, 长度 while r < len(s): look_up[s[r]] = look_up.get(s[r], 0) - 1 # 右指针填进去 if look_up[s[r]] >= 0: # 该元素是需要的,以后不一定需要 counter -= 1 while counter == 0: # 满足条件,剔除不需要的东西 if res[1] > r - l + 1: res = [l, r - l + 1] look_up[s[l]] += 1 # 需要的+1 if look_up[s[l]] > 0: # 踢了之后需要的元素缺少 counter += 1 l += 1 r += 1 if res[1] < float('inf'): return s[res[0]: res[0]+res[1]] else: return "" """ 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-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-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
博文转载请注明出处。