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,11,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)
相关推荐
手写码匠20 小时前
华为云Flexus+DeepSeek征文|基于华为云Flexus X实例 + Dify + DeepSeek 构建企业级智能知识库问答系统实战
人工智能·深度学习·算法·aigc
凤凰院凶涛QAQ20 小时前
《Java版数据结构 & 集合类剖析》集合框架的封装设计与顺序表:“从 Iterable 到 ArrayList:集合框架的‘职业树“
java·开发语言·数据结构
吴可可12321 小时前
Win7上开发CAD2004自定义实体全解析
c++·算法
孟华苏21 小时前
怎么快速排查内存泄漏问题
java·开发语言·python
YXXY31321 小时前
二叉树中的深搜算法介绍
算法
zz345729811321 小时前
C语言中字符串常量存储位置
c语言·开发语言·算法·青少年编程
noipp21 小时前
推荐题目:洛谷 P16510 [GKS 2015 #C] gRanks
java·c语言·开发语言·c++·python·算法
郑洁文21 小时前
基于Python的HTTP服务漏洞信息收集工具设计与实现
开发语言·python·http
川石课堂软件测试21 小时前
零基础小白如何学习自动化测试
python·功能测试·学习·测试工具·jmeter·压力测试·harmonyos
菜菜的顾清寒21 小时前
力扣HOT100(50)动态规划-零钱兑换
算法·leetcode·动态规划