LeetcodeDay15 不定长滑动窗口

模版

python 复制代码
l = 0
  for r in range(n):
  	count[r] += 1

	while (不满足):
		count[l] -= 1
		l += 1

3 无重复的最长连续子串

python 复制代码
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        count = {}
        res = 0
        n = len(s)
        l = 0
        for r in range(n):
            c = s[r]
            count[c] = count.get(c, 0) + 1
            while count[c] > 1:
                count[s[l]] -= 1
                l += 1
            res = max(res, r - l + 1)
        return res

76 最小覆盖子串

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

注意:

对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。

如果 s 中存在这样的子串,我们保证它是唯一的答案。

示例 1:

输入:s = "ADOBECODEBANC", t = "ABC"

输出:"BANC"

解释:最小覆盖子串 "BANC" 包含来自字符串 t 的 'A'、'B' 和 'C'。

python 复制代码
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        ans_left, ans_right = -1, len(s)
        left = 0
        cnt_s = Counter()  # s 子串字母的出现次数
        cnt_t = Counter(t)  # t 中字母的出现次数
        for right, c in enumerate(s):  # 移动子串右端点
            cnt_s[c] += 1  # 右端点字母移入子串
            while cnt_s >= cnt_t:  # 涵盖
                if right - left < ans_right - ans_left:  # 找到更短的子串
                    ans_left, ans_right = left, right  # 记录此时的左右端点
                cnt_s[s[left]] -= 1  # 左端点字母移出子串
                left += 1  # 移动子串左端点
        return "" if ans_left < 0 else s[ans_left: ans_right + 1]

注意counter的用法, 可直接用>=; 同时咱们对答案的更新应该在while内部

209 最小长度的连续子数组s.t. 之和大于target

(略)

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的

子数组

numsl, numsl+1, ..., numsr-1, numsr\] ,并返回其长度。如果不存在符合条件的子数组,返回 0 ## 904 只能拿两种水果 ```python class Solution: def totalFruit(self, fruits: List[int]) -> int: count = {} l = 0 ans = 0 for r in range(len(fruits)): count[fruits[r]] = count.get(fruits[r], 0) + 1 while (len(count)) > 2: count[fruits[l]] -= 1 if count[fruits[l]] == 0: count.pop(fruits[l]) l += 1 ans = max(ans, r - l + 1) return ans ``` ## 992. K 个不同整数的子数组 给定一个正整数数组 nums和一个整数 k,返回 nums 中 「好子数组」 的数目。 如果 nums 的某个子数组中不同整数的个数恰好为 k,则称 nums 的这个连续、不一定不同的子数组为 「好子数组 」。 输入:nums = \[1,2,1,2,3\], k = 2 输出:7 解释:恰好由 2 个不同整数组成的子数组:\[1,2\], \[2,1\], \[1,2\], \[2,3\], \[1,2,1\], \[2,1,2\], \[1,2,1,2\]. 一开始我的做法还是: ```python class Solution: def subarraysWithKDistinct(self, nums: List[int], k: int) -> int: count = {} l = 0 ans = 0 for r in range(len(nums)): count[nums[r]] = count.get(nums[r], 0) + 1 while len(count) > k: count[nums[l]] -= 1 if count[nums[l]] == 0: count.pop(nums[l]) l += 1 ans += r - l + 1 return ans ``` 其实这只解决最多`k`个的情况, 不是恰好k, 那我们直接用`最多k` 减去`最多k-1`不就可以了 ```python class Solution: def subarraysWithKDistinct(self, nums: List[int], k: int) -> int: def helper(k): ans = 0 n = len(nums) l = 0 g = defaultdict(int) for r, x in enumerate(nums): g[x] += 1 while len(g) > k: g[nums[l]] -= 1 if g[nums[l]] == 0: del g[nums[l]] l += 1 # 从上面循环出来一定保证g.keys() == k ans += r - l + 1 return ans return helper(k) - helper(k-1) ``` ## 1658. 将 x 减到 0 的最小操作数 给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。 如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。 > 灵神一句话, 正难则反, 直接点通任督二脉, 求`两边 = x`\<=\> `中间=sum - x`, 则转化为求最长子数组s.t.和为`sum - x` ```python class Solution: def minOperations(self, nums: List[int], x: int) -> int: target = sum(nums) - x if target < 0: return -1 # 全部移除也无法满足要求 ans = -1 left = s = 0 for right, x in enumerate(nums): s += x while s > target: # 缩小子数组长度 s -= nums[left] left += 1 if s == target: ans = max(ans, right - left + 1) return -1 if ans < 0 else len(nums) - ans ``` ## 1004 最大连续1的个数 III 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。 输入:nums = \[1,1,1,0,0,0,1,1,1,1,0\], K = 2 输出:6 解释:\[1,1,1,0,0,1,1,1,1,1,1

粗体数字从 0 翻转到 1,最长的子数组长度为 6。

一句话, 窗口内最多k个0

python 复制代码
class Solution:
    def longestOnes(self, nums: List[int], k: int) -> int:
        # 转换为滑动窗口, 窗口内最多k个0
        count = 0
        l = 0
        n = len(nums)
        ans = 0
        for r in range(len(nums)):
            if nums[r] == 0:
                count += 1
            while count > k:
                if nums[l] == 0:
                    count -= 1
                l += 1
            ans = max(ans, r - l + 1)
        return ans

1248 统计恰好k个奇数的数组数量

给你一个整数数组 nums 和一个整数 k。如果某个连续子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。

请返回这个数组中 「优美子数组」 的数目。

输入:nums = [1,1,2,1,1], k = 3

输出:2

解释:包含 3 个奇数的子数组是 [1,1,2,1] 和 [1,2,1,1] 。

python 复制代码
class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        def help(k):
            l = 0
            n = len(nums)
            ans = 0
            count = 0  # 计数奇数的个数,而不是使用字典
            for r in range(n):
                if nums[r] % 2 == 1:
                    count += 1
                while count > k:
                    if nums[l] % 2 == 1:
                        count -= 1
                    l += 1
                ans += r - l + 1
            return ans
        return help(k) - help(k-1)
相关推荐
元亓亓亓2 小时前
Java后端开发day36--源码解析:HashMap
java·开发语言·数据结构
酷ku的森3 小时前
数据结构:链表
数据结构·链表
何其有幸.4 小时前
实验3-3 比较大小(PTA|C语言)
c语言·数据结构·算法
fish_study_csdn5 小时前
pytest 技术总结
开发语言·python·pytest
咖啡调调。5 小时前
使用Django框架表单
后端·python·django
丶Darling.5 小时前
26考研 | 王道 | 数据结构笔记博客总结
数据结构·笔记·考研
BO_S__5 小时前
python调用ffmpeg对截取视频片段,可批量处理
python·ffmpeg·音视频
就叫飞六吧5 小时前
如何判断你的PyTorch是GPU版还是CPU版?
人工智能·pytorch·python
东阳马生架构6 小时前
Sentinel源码—8.限流算法和设计模式总结二
算法·设计模式·sentinel
老饼讲解-BP神经网络6 小时前
一篇入门之-评分卡变量分箱(卡方分箱、决策树分箱、KS分箱等)实操例子
算法·决策树·机器学习