当前位置: 首页 > news >正文

leetcode3258:统计满足K约束的子字符串数量Ⅰ(变长滑动窗口详解)

文章目录

  • 一、 题目描述
  • 二、 核心思路:变长滑动窗口 + 计数原理
  • 三、 代码实现与深度解析
  • 四、 关键点与复杂度分析

LeetCode 3258 统计满足 K 约束的子字符串,【难度:简答;通过率:83.8%】,这道题不再是简单地寻找最长/最短或最优值的窗口,而是要求我们 统计所有满足条件的 子数组的数量。这需要我们对滑动窗口的理解更进一步,核心思路没变,只是不能死板套一个固定的窗口来无脑遍历了

一、 题目描述

给你一个二进制字符串 s 和一个整数 k

如果一个子字符串中 0 的数目至多k 1 的数目至多k,则称其为满足 K 约束的子字符串

请你返回 s 中满足 K 约束的子字符串的数目(子字符串 是字符串中连续的 非空 字符序列)

示例:

示例 1:

输入:s = "10101", k = 1
输出:12解释:
s 的所有子字符串中,除了 "1010"、"10101" 和 "0101" 外,其余子字符串都满足 k 约束

示例 2:

输入:s = "1010101", k = 2
输出:25解释:
s 的所有子字符串中,除了长度大于 5 的子字符串外,其余子字符串都满足 k 约束

二、 核心思路:变长滑动窗口 + 计数原理

这道题的核心是统计所有满足条件的子数组。如果我们暴力枚举所有子数组,时间复杂度会是 O(),无法接受。因此,我们自然地想到了滑动窗口

但是,滑动窗口如何用来“计数”呢?这里有一个非常重要且显然的原理:

如果一个以 r 为右端点的窗口 [l, r] 是满足条件的,那么所有以 r 为右端点、且被 [l, r] 包含的子数组,也一定满足条件。

例如,如果 s = "01101"k=2,当我们的窗口是 [0, 1, 1] (l=0, r=2) 时,它是满足条件的。那么,以 r=2(即第三个 ‘1’)结尾的、满足条件的子数组有哪些?

  • [1] (从 r=2 开始)
  • [1, 1] (从 r=1 开始)
  • [0, 1, 1] (从 r=0 开始)
    总共有 r - l + 1 = 2 - 0 + 1 = 3

基于这个原理,我们的算法流程就清晰了:

  1. 用右指针 r 遍历字符串,不断扩大窗口
  2. 在每一步,我们检查当前窗口 [l, r] 是否满足条件 (0 的数量 <=k1 的数量 <=k)
  3. 如果不满足,我们就从左边收缩窗口l++),直到窗口重新满足条件为止
  4. 当窗口 [l, r] 满足条件后,我们就知道,所有以 r 结尾的、长度不超过 r-l+1 的子数组都满足条件。我们将这个数量 r - l + 1 累加到最终结果 ans

三、 代码实现与深度解析

【最佳实践】

class Solution {public int countKConstraintSubstrings(String s, int k) {int ans = 0;int left = 0; // 滑动窗口的左边界// cnt[0] 记录 '0' 的数量, cnt[1] 记录 '1' 的数量int[] counts = new int[2]; // right 是滑动窗口的右边界for (int right = 0; right < s.length(); right++) {// 步骤 1: 右边界进入窗口,更新状态counts[s.charAt(right) - '0']++;// 步骤 2: 检查窗口是否合法。如果不合法,则收缩左边界// 只要 '0' 或 '1' 的数量超过 k,窗口就不合法while (counts[0] > k || counts[1] > k) {// 将左边界的字符移出窗口counts[s.charAt(left) - '0']--;left++; // 收缩窗口}// 步骤 3: 此时的窗口 [left, right] 是一个满足条件的窗口// 所有以 right 结尾的子数组,只要其左边界不小于 left,就都是合法的// 这样的子数组有 (right - left + 1) 个ans += (right - left + 1);}return ans;}
}

注意:while循环中的条件是 “或 ||”,不要理解错题意理解为了 “且 &&”(尽管写成 && 的逻辑也能过)

提交结果:

在这里插入图片描述


四、 关键点与复杂度分析

  • 计数原理ans += (right - left + 1) 是本题的精髓,它将滑动窗口从一个“查找”工具,变成了一个“计数”工具
  • 窗口的收缩条件while (counts[0] > k || counts[1] > k) 准确地反映了题目的约束条件。只要有一个不满足,就需要收缩
  • 时间复杂度O(N) 虽然有 while 循环嵌套在 for 循环中,但每个元素最多被左指针 left 和右指针 right 各访问一次。因此,总的时间复杂度是线性的
  • 空间复杂度O(1) 我们只使用了大小为 2 的 counts 数组,空间开销是常数级别的
http://www.lryc.cn/news/618877.html

相关文章:

  • Tricentis Tosca 2025.1 LTS 系统要求
  • Java 中 Set 接口详解:知识点与注意事项
  • Day50--图论--98. 所有可达路径(卡码网),797. 所有可能的路径
  • Javase 之 字符串String类
  • Python 多进程及进程间通信
  • C++实现LINGO模型处理程序
  • 杰里常用功能API
  • Navicat更改MySql表名后IDEA项目启动会找原来的表
  • 腾讯codebuddy.ai 安装实测【从零开始开发在线五子棋游戏:完整开发记录】
  • 服务降级方式
  • 2025年最新原创多目标算法:多目标酶作用优化算法(MOEAO)求解MaF1-MaF15及工程应用---盘式制动器设计,提供完整MATLAB代码
  • 拖动式看板工具TOP6:2025最新评测
  • 疯狂星期四文案网第37天运营日记
  • 看懂 Makefile 第一课:基础
  • 企业培训笔记:宠物信息管理--实现宠物信息的添加
  • c#,vb.net全局多线程锁,可以在任意模块或类中使用,但尽量用多个锁提高效率
  • 行业分享丨SimSolid 在汽车零部件开发中应用的可行性调研及实践
  • 基于Hadoop的汽车价格预测分析及评论情感分析可视化系统
  • 海信IP108H(53U1M)_S905L-B主控-无线SV6051P/8822CS(通刷咪咕mg100_mg101)线刷固件包
  • grpc浅入门
  • 一键生成 Android 适配不同分辨率尺寸的图片
  • 什么是 Spring MVC?
  • AuthController类讲解
  • 龙舌兰人造植物、Apple Watch保护壳、厨房水槽收纳架、家居磁性挂钩等亚马逊热销单品,正在外观专利TRO维权!
  • 备战国赛算法讲解——马尔科夫链,2025国赛数学建模B题详细思路模型更新
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-会议记录
  • Linux网络--2.2、TCP接口
  • 5 重复匹配
  • 51 单片机分层架构的模块依赖关系图
  • 详细解释RBFT和NoxBFT及RAFT的差异